aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/crepe/Particle.h1
-rw-r--r--src/crepe/system/ParticleSystem.cpp157
-rw-r--r--src/crepe/system/ParticleSystem.h61
3 files changed, 115 insertions, 104 deletions
diff --git a/src/crepe/Particle.h b/src/crepe/Particle.h
index 77c3ea3..88a015d 100644
--- a/src/crepe/Particle.h
+++ b/src/crepe/Particle.h
@@ -14,6 +14,7 @@ namespace crepe {
* to simulate movement and can also be reset or stopped.
*/
class Particle {
+ // TODO: add friend particleSsytem and rendersystem. Unit test will fail.
public:
//! Position of the particle in 2D space.
Vector2 position;
diff --git a/src/crepe/system/ParticleSystem.cpp b/src/crepe/system/ParticleSystem.cpp
index e6dc670..a0b1e55 100644
--- a/src/crepe/system/ParticleSystem.cpp
+++ b/src/crepe/system/ParticleSystem.cpp
@@ -13,151 +13,112 @@ using namespace crepe;
ParticleSystem::ParticleSystem() {}
void ParticleSystem::update() {
-
// Get all emitters
ComponentManager & mgr = ComponentManager::get_instance();
- std::vector<std::reference_wrapper<ParticleEmitter>> emitters
- = mgr.get_components_by_type<ParticleEmitter>();
+ std::vector<std::reference_wrapper<ParticleEmitter>> emitters = mgr.get_components_by_type<ParticleEmitter>();
for (ParticleEmitter & emitter : emitters) {
-
- // Get transform linked to emitter
+ // Get transform linked to emitter
const Transform& transform = mgr.get_components_by_id<Transform>(emitter.game_object_id).front().get();
-
// Emit particles based on emission_rate
- int updates = calculate_update(this->update_count,emitter.data.emission_rate);
- for (size_t i = 0; i < updates; i++)
- {
- emit_particle(emitter,transform);
+ int updates = calculate_update(this->update_count, emitter.data.emission_rate);
+ for (size_t i = 0; i < updates; i++) {
+ emit_particle(emitter, transform);
}
-
+
// Update all particles
- for (size_t j = 0; j < emitter.data.particles.size(); j++) {
- if (emitter.data.particles[j].active) {
- emitter.data.particles[j].update();
+ for (Particle& particle : emitter.data.particles) {
+ if (particle.active) {
+ particle.update();
}
}
- // Check if within boundary
- check_bounds(emitter,transform);
+ // Check if within boundary
+ check_bounds(emitter, transform);
}
- update_count++;
- if(update_count == MAX_UPDATE_COUNT) update_count = 0;
+ update_count = (update_count + 1) % MAX_UPDATE_COUNT;
}
-void ParticleSystem::emit_particle(ParticleEmitter & emitter,const Transform& transform) {
+void ParticleSystem::emit_particle(ParticleEmitter & emitter, const Transform& transform) {
constexpr double DEG_TO_RAD = M_PI / 180.0;
Vector2 initial_position = emitter.data.position + transform.position;
- double min_angle = emitter.data.min_angle;
- double max_angle = emitter.data.max_angle;
- double random_angle;
- if(min_angle == max_angle){
- random_angle = min_angle;
- }
- else if (min_angle <= max_angle) {
- // Standard range (e.g., 10 to 20 degrees)
- double angle_offset = max_angle - min_angle;
- random_angle = min_angle + static_cast<double>(std::rand() % static_cast<uint32_t>(angle_offset));
- } else {
- // Wrap-around range (e.g., 350 to 10 degrees)
- double angle_offset = (360 - min_angle) + max_angle;
- random_angle = min_angle + static_cast<double>(std::rand() % static_cast<uint32_t>(angle_offset));
-
- // Wrap around to keep random_angle within 0-360 degrees
- if (random_angle >= 360) {
- random_angle -= 360;
- }
- }
+ double random_angle = generate_random_angle(emitter.data.min_angle, emitter.data.max_angle);
- // Generate a random speed between min_speed and max_speed
- double speed_offset = emitter.data.max_speed - emitter.data.min_speed;
- double random_speed = 0.0;
- if(emitter.data.max_speed == emitter.data.min_speed)
- {
- random_speed = emitter.data.min_speed;
- }
- else {
- random_speed = emitter.data.min_speed + static_cast<double>(std::rand() % static_cast<uint32_t>(speed_offset));
- }
-
- // Convert random_angle to radians
+ double random_speed = generate_random_speed(emitter.data.min_speed, emitter.data.max_speed);
double angle_radians = random_angle * DEG_TO_RAD;
Vector2 velocity = {
- random_speed * std::cos(angle_radians),
- random_speed * std::sin(angle_radians)
- };
+ random_speed * std::cos(angle_radians),
+ random_speed * std::sin(angle_radians)
+ };
-
- for (size_t i = 0; i < emitter.data.particles.size(); i++) {
- if (!emitter.data.particles[i].active) {
- emitter.data.particles[i].reset(emitter.data.end_lifespan, initial_position,velocity,random_angle);
+ for (Particle& particle : emitter.data.particles) {
+ if (!particle.active) {
+ particle.reset(emitter.data.end_lifespan, initial_position, velocity, random_angle);
break;
}
}
}
-int ParticleSystem::calculate_update(int count, double emission) {
-
- //get interger part of the emission
+int ParticleSystem::calculate_update(int count, double emission) const {
double integer_part = std::floor(emission);
-
- // Get the fractional part of the emission
double fractional_part = emission - integer_part;
- // Convert the fractional part to a denominator value
- int denominator = static_cast<int>(1.0 / fractional_part);
-
- // For emissions like 0.01, 0.1, 0.5, etc., calculate the update frequency
if (fractional_part > 0) {
- // Calculate how often the update should be triggered based on the fractional part
- if (count % denominator == 0) {
- return 1;
- } else {
- return 0;
- }
+ int denominator = static_cast<int>(1.0 / fractional_part);
+ return (count % denominator == 0) ? 1 : 0;
}
-
- // For integer emissions, return the emission directly
+
return static_cast<int>(emission);
}
-void ParticleSystem::check_bounds(ParticleEmitter & emitter,const Transform& transform)
-{
+void ParticleSystem::check_bounds(ParticleEmitter & emitter, const Transform& transform) {
Vector2 offset = emitter.data.boundary.offset + transform.position + emitter.data.position;
double half_width = emitter.data.boundary.width / 2.0;
double half_height = emitter.data.boundary.height / 2.0;
- // Define boundary edges
- const double left = offset.x - half_width;
- const double right = offset.x + half_width;
- const double top = offset.y - half_height;
- const double bottom = offset.y + half_height;
+ const double LEFT = offset.x - half_width;
+ const double RIGHT = offset.x + half_width;
+ const double TOP = offset.y - half_height;
+ const double BOTTOM = offset.y + half_height;
- std::vector<Particle>& particles = emitter.data.particles;
- for (Particle& particle : particles)
- {
+ for (Particle& particle : emitter.data.particles) {
const Vector2& position = particle.position;
+ bool within_bounds = (position.x >= LEFT && position.x <= RIGHT && position.y >= TOP && position.y <= BOTTOM);
- // Check if particle is within bounds
- bool within_bounds = (position.x >= left && position.x <= right && position.y >= top && position.y <= bottom);
- if (!within_bounds)
- {
- if (emitter.data.boundary.reset_on_exit)
- {
+ if (!within_bounds) {
+ if (emitter.data.boundary.reset_on_exit) {
particle.active = false;
- }
- else
- {
+ } else {
particle.velocity = {0, 0};
- if (particle.position.x < left) particle.position.x = left;
- else if (particle.position.x > right) particle.position.x = right;
- if (particle.position.y < bottom) particle.position.y = bottom;
- else if (particle.position.y > top) particle.position.y = top;
+ if (position.x < LEFT) particle.position.x = LEFT;
+ else if (position.x > RIGHT) particle.position.x = RIGHT;
+ if (position.y < TOP) particle.position.y = TOP;
+ else if (position.y > BOTTOM) particle.position.y = BOTTOM;
}
}
}
}
+
+double ParticleSystem::generate_random_angle(double min_angle, double max_angle) const {
+ if (min_angle == max_angle) {
+ return min_angle;
+ } else if (min_angle < max_angle) {
+ return min_angle + static_cast<double>(std::rand() % static_cast<int>(max_angle - min_angle));
+ } else {
+ double angle_offset = (360 - min_angle) + max_angle;
+ double random_angle = min_angle + static_cast<double>(std::rand() % static_cast<int>(angle_offset));
+ return (random_angle >= 360) ? random_angle - 360 : random_angle;
+ }
+}
+
+double ParticleSystem::generate_random_speed(double min_speed, double max_speed) const {
+ if (min_speed == max_speed) {
+ return min_speed;
+ } else {
+ return min_speed + static_cast<double>(std::rand() % static_cast<int>(max_speed - min_speed));
+ }
+}
diff --git a/src/crepe/system/ParticleSystem.h b/src/crepe/system/ParticleSystem.h
index 3b9cb54..df89ed9 100644
--- a/src/crepe/system/ParticleSystem.h
+++ b/src/crepe/system/ParticleSystem.h
@@ -4,21 +4,70 @@
namespace crepe {
+/**
+ * \brief ParticleSystem class responsible for managing particle emission, updates, and bounds checking.
+ */
class ParticleSystem {
public:
+ /**
+ * \brief Default constructor.
+ */
ParticleSystem();
+
+ /**
+ * \brief Updates all particle emitters by emitting particles, updating particle states, and checking bounds.
+ */
void update();
private:
- void emit_particle(ParticleEmitter & emitter,const Transform& transform);
- int calculate_update(int count, double emission);
- void check_bounds(ParticleEmitter & emitter,const Transform& transform);
+ /**
+ * \brief Emits a particle from the specified emitter based on its emission properties.
+ *
+ * \param emitter Reference to the ParticleEmitter.
+ * \param transform Const reference to the Transform component associated with the emitter.
+ */
+ void emit_particle(ParticleEmitter & emitter, const Transform& transform);
+
+ /**
+ * \brief Calculates the number of times particles should be emitted based on emission rate and update count.
+ *
+ * \param count Current update count.
+ * \param emission Emission rate.
+ * \return The number of particles to emit.
+ */
+ int calculate_update(int count, double emission) const;
+
+ /**
+ * \brief Checks whether particles are within the emitter’s boundary, resets or stops particles if they exit.
+ *
+ * \param emitter Reference to the ParticleEmitter.
+ * \param transform Const reference to the Transform component associated with the emitter.
+ */
+ void check_bounds(ParticleEmitter & emitter, const Transform& transform);
+
+ /**
+ * \brief Generates a random angle for particle emission within the specified range.
+ *
+ * \param min_angle Minimum emission angle in degrees.
+ * \param max_angle Maximum emission angle in degrees.
+ * \return Random angle in degrees.
+ */
+ double generate_random_angle(double min_angle, double max_angle) const;
+
+ /**
+ * \brief Generates a random speed for particle emission within the specified range.
+ *
+ * \param min_speed Minimum emission speed.
+ * \param max_speed Maximum emission speed.
+ * \return Random speed.
+ */
+ double generate_random_speed(double min_speed, double max_speed) const;
private:
- //! counter to count updates to determine how many times emit_particle is called.
+ //! Counter to count updates to determine how many times emit_particle is called.
uint32_t update_count = 0;
- //! determines the lowest amount of emissionrate (1000 = 0.001 = 1 particle per 1000 updates).
- const uint32_t MAX_UPDATE_COUNT = 100;
+ //! Determines the lowest amount of emission rate (1000 = 0.001 = 1 particle per 1000 updates).
+ static constexpr uint32_t MAX_UPDATE_COUNT = 100;
};
} // namespace crepe