diff options
-rw-r--r-- | src/crepe/system/ParticleSystem.cpp | 101 | ||||
-rw-r--r-- | src/test/ParticleTest.cpp | 54 |
2 files changed, 102 insertions, 53 deletions
diff --git a/src/crepe/system/ParticleSystem.cpp b/src/crepe/system/ParticleSystem.cpp index 48fe1d7..e6dc670 100644 --- a/src/crepe/system/ParticleSystem.cpp +++ b/src/crepe/system/ParticleSystem.cpp @@ -24,8 +24,6 @@ void ParticleSystem::update() { // Get transform linked to emitter const Transform& transform = mgr.get_components_by_id<Transform>(emitter.game_object_id).front().get(); - // Check if within boundary - check_bounds(emitter,transform); // Emit particles based on emission_rate int updates = calculate_update(this->update_count,emitter.data.emission_rate); @@ -40,7 +38,11 @@ void ParticleSystem::update() { emitter.data.particles[j].update(); } } + + // Check if within boundary + check_bounds(emitter,transform); } + update_count++; if(update_count == MAX_UPDATE_COUNT) update_count = 0; } @@ -100,59 +102,62 @@ void ParticleSystem::emit_particle(ParticleEmitter & emitter,const Transform& tr int ParticleSystem::calculate_update(int count, double emission) { - //get interger part of the emission - double integer_part = std::floor(emission); + //get interger part of the emission + double integer_part = std::floor(emission); - // Get the fractional part of the emission - double fractional_part = emission - integer_part; + // 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); + // 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; - } - } - - // For integer emissions, return the emission directly - return static_cast<int>(emission); + // 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; + } + } + + // For integer emissions, return the emission directly + return static_cast<int>(emission); } 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; - - std::vector<Particle>& particles = emitter.data.particles; - for (Particle& particle : particles) + 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; + + std::vector<Particle>& particles = emitter.data.particles; + for (Particle& particle : particles) + { + const Vector2& position = particle.position; + + // Check if particle is within bounds + bool within_bounds = (position.x >= left && position.x <= right && position.y >= top && position.y <= bottom); + if (!within_bounds) { - const Vector2& position = particle.position; - - // 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) - { - particle.active = false; - } - else - { - particle.velocity = {0, 0}; - //todo add that particle goes back to boundary - } - } + if (emitter.data.boundary.reset_on_exit) + { + particle.active = false; + } + 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; + } } + } } diff --git a/src/test/ParticleTest.cpp b/src/test/ParticleTest.cpp index 1b949e3..8c6a7e7 100644 --- a/src/test/ParticleTest.cpp +++ b/src/test/ParticleTest.cpp @@ -1,3 +1,4 @@ +#include "api/Vector2.h" #include <math.h> #include <crepe/ComponentManager.h> #include <crepe/api/Config.h> @@ -80,17 +81,17 @@ TEST_F(ParticlesTest, spawnParticle) { emitter.data.max_angle = 10; particle_system.update(); //check if nothing happend - EXPECT_EQ(emitter.data.particles[0].active, 0); + EXPECT_EQ(emitter.data.particles[0].active, false); emitter.data.emission_rate = 1; //check particle spawnes particle_system.update(); - EXPECT_EQ(emitter.data.particles[0].active, 1); + EXPECT_EQ(emitter.data.particles[0].active, true); particle_system.update(); - EXPECT_EQ(emitter.data.particles[1].active, 1); + EXPECT_EQ(emitter.data.particles[1].active, true); particle_system.update(); - EXPECT_EQ(emitter.data.particles[2].active, 1); + EXPECT_EQ(emitter.data.particles[2].active, true); particle_system.update(); - EXPECT_EQ(emitter.data.particles[3].active, 1); + EXPECT_EQ(emitter.data.particles[3].active, true); for (auto& particle : emitter.data.particles) { // Check velocity range @@ -141,3 +142,46 @@ TEST_F(ParticlesTest, moveParticleVertical) { EXPECT_EQ(emitter.data.particles[0].position.y,a); } } + +TEST_F(ParticlesTest, boundaryParticleReset) { + Config::get_instance().physics.gravity = 1; + ComponentManager & mgr = ComponentManager::get_instance(); + ParticleEmitter & emitter = mgr.get_components_by_id<ParticleEmitter>(0).front().get(); + emitter.data.end_lifespan = 100; + emitter.data.boundary.height = 10; + emitter.data.boundary.width = 10; + emitter.data.boundary.reset_on_exit = true; + emitter.data.min_speed = 1; + emitter.data.max_speed = 1; + emitter.data.min_angle = 90; + emitter.data.max_angle = 90; + emitter.data.emission_rate = 1; + for (int a = 0; a < emitter.data.boundary.width/2+1; a++) { + particle_system.update(); + } + EXPECT_EQ(emitter.data.particles[0].active,false); +} + +TEST_F(ParticlesTest, boundaryParticleStop) { + Config::get_instance().physics.gravity = 1; + ComponentManager & mgr = ComponentManager::get_instance(); + ParticleEmitter & emitter = mgr.get_components_by_id<ParticleEmitter>(0).front().get(); + emitter.data.end_lifespan = 100; + emitter.data.boundary.height = 10; + emitter.data.boundary.width = 10; + emitter.data.boundary.reset_on_exit = false; + emitter.data.min_speed = 1; + emitter.data.max_speed = 1; + emitter.data.min_angle = 90; + emitter.data.max_angle = 90; + emitter.data.emission_rate = 1; + for (int a = 0; a < emitter.data.boundary.width/2+1; a++) { + particle_system.update(); + } + const double TOLERANCE = 0.01; + EXPECT_NEAR(emitter.data.particles[0].velocity.x, 0, TOLERANCE); + EXPECT_NEAR(emitter.data.particles[0].velocity.y, 0, TOLERANCE); + if(emitter.data.particles[0].velocity.x != 0) EXPECT_NEAR(std::abs(emitter.data.particles[0].position.x), emitter.data.boundary.height / 2, TOLERANCE); + if(emitter.data.particles[0].velocity.y != 0) EXPECT_NEAR(std::abs(emitter.data.particles[0].position.y), emitter.data.boundary.width / 2, TOLERANCE); +} + |