diff options
-rw-r--r-- | src/crepe/Particle.cpp | 13 | ||||
-rw-r--r-- | src/crepe/Particle.h | 11 | ||||
-rw-r--r-- | src/crepe/api/Config.h | 2 | ||||
-rw-r--r-- | src/crepe/api/ParticleEmitter.cpp | 5 | ||||
-rw-r--r-- | src/crepe/api/ParticleEmitter.h | 31 | ||||
-rw-r--r-- | src/crepe/api/Rigidbody.h | 2 | ||||
-rw-r--r-- | src/crepe/system/AISystem.cpp | 2 | ||||
-rw-r--r-- | src/crepe/system/CollisionSystem.cpp | 3 | ||||
-rw-r--r-- | src/crepe/system/ParticleSystem.cpp | 60 | ||||
-rw-r--r-- | src/crepe/system/ParticleSystem.h | 15 | ||||
-rw-r--r-- | src/crepe/system/PhysicsSystem.cpp | 119 | ||||
-rw-r--r-- | src/test/PhysicsTest.cpp | 2 |
12 files changed, 126 insertions, 139 deletions
diff --git a/src/crepe/Particle.cpp b/src/crepe/Particle.cpp index 485a0d4..b340826 100644 --- a/src/crepe/Particle.cpp +++ b/src/crepe/Particle.cpp @@ -2,8 +2,8 @@ using namespace crepe; -void Particle::reset(uint32_t lifespan, const vec2 & position, const vec2 & velocity, - double angle) { +void Particle::reset(unsigned int lifespan, const vec2 & position, const vec2 & velocity, + float angle) { // Initialize the particle state this->time_in_life = 0; this->lifespan = lifespan; @@ -15,16 +15,17 @@ void Particle::reset(uint32_t lifespan, const vec2 & position, const vec2 & velo this->force_over_time = {0, 0}; } -void Particle::update() { +void Particle::update(double dt) { // Deactivate particle if it has exceeded its lifespan - if (++time_in_life >= lifespan) { + time_in_life += dt; + if (time_in_life >= lifespan) { this->active = false; return; } // Update velocity based on accumulated force and update position - this->velocity += force_over_time; - this->position += velocity; + this->velocity += force_over_time * dt; + this->position += velocity * dt; } void Particle::stop_movement() { diff --git a/src/crepe/Particle.h b/src/crepe/Particle.h index d0397c9..49fec1f 100644 --- a/src/crepe/Particle.h +++ b/src/crepe/Particle.h @@ -24,13 +24,13 @@ public: //! Accumulated force affecting the particle over time. vec2 force_over_time; //! Total lifespan of the particle in milliseconds. - uint32_t lifespan; + float lifespan; //! Active state of the particle; true if it is in use, false otherwise. bool active = false; //! The time the particle has been alive, in milliseconds. - uint32_t time_in_life = 0; + float time_in_life = 0; //! The angle at which the particle is oriented or moving. - double angle = 0; + float angle = 0; /** * \brief Resets the particle with new properties. @@ -43,14 +43,15 @@ public: * \param velocity The initial velocity of the particle. * \param angle The angle of the particle's trajectory or orientation. */ - void reset(uint32_t lifespan, const vec2 & position, const vec2 & velocity, double angle); + void reset(unsigned int lifespan, const vec2 & position, const vec2 & velocity, float angle); /** * \brief Updates the particle's state. * * Advances the particle's position based on its velocity and applies accumulated forces. * Deactivates the particle if its lifespan has expired. + * \param dt The amount of fixed delta time that has passed. */ - void update(); + void update(double dt); /** * \brief Stops the particle's movement. * diff --git a/src/crepe/api/Config.h b/src/crepe/api/Config.h index 6472270..cd27343 100644 --- a/src/crepe/api/Config.h +++ b/src/crepe/api/Config.h @@ -53,7 +53,7 @@ struct Config final { * * Gravity value of game. */ - double gravity = 1; + float gravity = 1; } physics; //! default window settings diff --git a/src/crepe/api/ParticleEmitter.cpp b/src/crepe/api/ParticleEmitter.cpp index 90b77a0..1cfdceb 100644 --- a/src/crepe/api/ParticleEmitter.cpp +++ b/src/crepe/api/ParticleEmitter.cpp @@ -1,10 +1,11 @@ #include "ParticleEmitter.h" +#include "api/Sprite.h" using namespace crepe; -ParticleEmitter::ParticleEmitter(game_object_id_t game_object_id, const Data & data) +ParticleEmitter::ParticleEmitter(game_object_id_t game_object_id, const Sprite & sprite, const Data & data) : Component(game_object_id), - data(data) { + sprite(sprite), data(data) { for (size_t i = 0; i < this->data.max_particles; i++) { this->data.particles.emplace_back(); } diff --git a/src/crepe/api/ParticleEmitter.h b/src/crepe/api/ParticleEmitter.h index b83fd61..48c7625 100644 --- a/src/crepe/api/ParticleEmitter.h +++ b/src/crepe/api/ParticleEmitter.h @@ -1,5 +1,6 @@ #pragma once +#include <cmath> #include <vector> #include "Component.h" @@ -26,15 +27,18 @@ public: */ struct Boundary { //! boundary width (midpoint is emitter location) - double width = 0.0; + float width = INFINITY; //! boundary height (midpoint is emitter location) - double height = 0.0; + float height = INFINITY; //! boundary offset from particle emitter location vec2 offset; //! reset on exit or stop velocity and set max postion bool reset_on_exit = false; }; + //! sprite reference of displayed sprite + const Sprite & sprite; + /** * \brief Holds parameters that control particle emission. * @@ -45,29 +49,30 @@ public: //! position of the emitter vec2 position; //! maximum number of particles - const unsigned int max_particles = 0; + const unsigned int max_particles = 256; //! rate of particle emission per update (Lowest value = 0.001 any lower is ignored) - double emission_rate = 0; + float emission_rate = 1; + //! Saves time left over from last update event. + float spawn_accumulator = 0; //! min speed of the particles - double min_speed = 0; + float min_speed = 1; //! min speed of the particles - double max_speed = 0; + float max_speed = 2; //! min angle of particle emission - double min_angle = 0; + float min_angle = 0; //! max angle of particle emission - double max_angle = 0; + float max_angle = 0; //! begin Lifespan of particle (only visual) - double begin_lifespan = 0.0; + float begin_lifespan = 0.0; //! end Lifespan of particle - double end_lifespan = 0.0; + float end_lifespan = 10.0; //! force over time (physics) vec2 force_over_time; //! particle boundary Boundary boundary; //! collection of particles std::vector<Particle> particles; - //! sprite reference - const Sprite & sprite; + }; public: @@ -75,7 +80,7 @@ public: * \param game_object_id Identifier for the game object using this emitter. * \param data Configuration data defining particle properties. */ - ParticleEmitter(game_object_id_t game_object_id, const Data & data); + ParticleEmitter(game_object_id_t game_object_id, const Sprite & sprite,const Data & data); public: //! Configuration data for particle emission settings. diff --git a/src/crepe/api/Rigidbody.h b/src/crepe/api/Rigidbody.h index 40c6bf1..f641fff 100644 --- a/src/crepe/api/Rigidbody.h +++ b/src/crepe/api/Rigidbody.h @@ -79,7 +79,7 @@ public: //! Linear velocity of the object (speed and direction). vec2 linear_velocity; //! Maximum linear velocity of the object. This limits the object's speed. - vec2 max_linear_velocity = {INFINITY, INFINITY}; + float max_linear_velocity = INFINITY; //! Linear velocity coefficient. This scales the object's velocity for adjustment or damping. vec2 linear_velocity_coefficient = {1, 1}; //! \} diff --git a/src/crepe/system/AISystem.cpp b/src/crepe/system/AISystem.cpp index d231c7c..1d8ffb9 100644 --- a/src/crepe/system/AISystem.cpp +++ b/src/crepe/system/AISystem.cpp @@ -146,7 +146,7 @@ vec2 AISystem::arrive(const AI & ai, const Rigidbody & rigidbody, } float speed = distance / ai.arrive_deceleration; - speed = std::min(speed, rigidbody.data.max_linear_velocity.length()); + speed = std::min(speed, rigidbody.data.max_linear_velocity); vec2 desired_velocity = to_target * (speed / distance); return desired_velocity - rigidbody.data.linear_velocity; diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp index 44a0431..dc5270e 100644 --- a/src/crepe/system/CollisionSystem.cpp +++ b/src/crepe/system/CollisionSystem.cpp @@ -290,7 +290,10 @@ vec2 CollisionSystem::get_circle_box_resolution(const CircleCollider & circle_co // Compute penetration depth float penetration_depth = circle_collider.radius - distance; +<<<<<<< HEAD +======= +>>>>>>> 05a33d4793520fa84a93bc79882ef29d39cd08e5 // Compute the resolution vector vec2 resolution = collision_normal * penetration_depth; diff --git a/src/crepe/system/ParticleSystem.cpp b/src/crepe/system/ParticleSystem.cpp index b14c52f..3befb03 100644 --- a/src/crepe/system/ParticleSystem.cpp +++ b/src/crepe/system/ParticleSystem.cpp @@ -12,8 +12,10 @@ using namespace crepe; void ParticleSystem::update() { // Get all emitters + ComponentManager & mgr = this->mediator.component_manager; RefVector<ParticleEmitter> emitters = mgr.get_components_by_type<ParticleEmitter>(); + double dt = LoopTimer::get_instance().get_fixed_delta_time(); for (ParticleEmitter & emitter : emitters) { // Get transform linked to emitter @@ -21,20 +23,21 @@ void ParticleSystem::update() { = 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); - } - + emitter.data.spawn_accumulator = emitter.data.emission_rate * dt; + while (emitter.data.spawn_accumulator >= 1.0) { + this->emit_particle(emitter, transform); + emitter.data.spawn_accumulator -= 1.0; + } + // Update all particles for (Particle & particle : emitter.data.particles) { if (particle.active) { - particle.update(); + particle.update(dt); } } // Check if within boundary - check_bounds(emitter, transform); + this->check_bounds(emitter, transform); } this->update_count = (this->update_count + 1) % this->MAX_UPDATE_COUNT; @@ -44,9 +47,9 @@ void ParticleSystem::emit_particle(ParticleEmitter & emitter, const Transform & constexpr float DEG_TO_RAD = M_PI / 180.0; vec2 initial_position = emitter.data.position + transform.position; - float random_angle = generate_random_angle(emitter.data.min_angle, emitter.data.max_angle); + float random_angle = this->generate_random_angle(emitter.data.min_angle, emitter.data.max_angle); - float random_speed = generate_random_speed(emitter.data.min_speed, emitter.data.max_speed); + float random_speed = this->generate_random_speed(emitter.data.min_speed, emitter.data.max_speed); float angle_radians = random_angle * DEG_TO_RAD; vec2 velocity @@ -61,33 +64,20 @@ void ParticleSystem::emit_particle(ParticleEmitter & emitter, const Transform & } } -int ParticleSystem::calculate_update(int count, double emission) const { - double integer_part = std::floor(emission); - double fractional_part = emission - integer_part; - - if (fractional_part > 0) { - int denominator = static_cast<int>(1.0 / fractional_part); - return (count % denominator == 0) ? 1 : 0; - } - - return static_cast<int>(emission); -} - void ParticleSystem::check_bounds(ParticleEmitter & emitter, const Transform & transform) { vec2 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; + float half_width = emitter.data.boundary.width / 2.0; + float half_height = emitter.data.boundary.height / 2.0; - 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 float LEFT = offset.x - half_width; + const float RIGHT = offset.x + half_width; + const float TOP = offset.y - half_height; + const float BOTTOM = offset.y + half_height; for (Particle & particle : emitter.data.particles) { const vec2 & position = particle.position; 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; @@ -102,25 +92,25 @@ void ParticleSystem::check_bounds(ParticleEmitter & emitter, const Transform & t } } -double ParticleSystem::generate_random_angle(double min_angle, double max_angle) const { +float ParticleSystem::generate_random_angle(float min_angle, float 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)); + + static_cast<float>(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)); + float angle_offset = (360 - min_angle) + max_angle; + float random_angle + = min_angle + static_cast<float>(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 { +float ParticleSystem::generate_random_speed(float min_speed, float 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)); + + static_cast<float>(std::rand() % static_cast<int>(max_speed - min_speed)); } } diff --git a/src/crepe/system/ParticleSystem.h b/src/crepe/system/ParticleSystem.h index 068f01c..454b65f 100644 --- a/src/crepe/system/ParticleSystem.h +++ b/src/crepe/system/ParticleSystem.h @@ -23,6 +23,7 @@ public: void update() override; private: + /** * \brief Emits a particle from the specified emitter based on its emission properties. * @@ -32,16 +33,6 @@ private: 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. * @@ -57,7 +48,7 @@ private: * \param max_angle Maximum emission angle in degrees. * \return Random angle in degrees. */ - double generate_random_angle(double min_angle, double max_angle) const; + float generate_random_angle(float min_angle, float max_angle) const; /** * \brief Generates a random speed for particle emission within the specified range. @@ -66,7 +57,7 @@ private: * \param max_speed Maximum emission speed. * \return Random speed. */ - double generate_random_speed(double min_speed, double max_speed) const; + float generate_random_speed(float min_speed, float max_speed) const; private: //! Counter to count updates to determine how many times emit_particle is diff --git a/src/crepe/system/PhysicsSystem.cpp b/src/crepe/system/PhysicsSystem.cpp index ebf4439..be768f9 100644 --- a/src/crepe/system/PhysicsSystem.cpp +++ b/src/crepe/system/PhysicsSystem.cpp @@ -11,82 +11,77 @@ using namespace crepe; void PhysicsSystem::update() { + double dt = LoopTimer::get_instance().get_fixed_delta_time(); ComponentManager & mgr = this->mediator.component_manager; RefVector<Rigidbody> rigidbodies = mgr.get_components_by_type<Rigidbody>(); - RefVector<Transform> transforms = mgr.get_components_by_type<Transform>(); + - double gravity = Config::get_instance().physics.gravity; + float gravity = Config::get_instance().physics.gravity; for (Rigidbody & rigidbody : rigidbodies) { if (!rigidbody.active) continue; + Transform & transform = mgr.get_components_by_id<Transform>(rigidbody.game_object_id).front().get(); switch (rigidbody.data.body_type) { case Rigidbody::BodyType::DYNAMIC: - for (Transform & transform : transforms) { - if (transform.game_object_id == rigidbody.game_object_id) { - - // Add gravity - if (rigidbody.data.gravity_scale > 0) { - rigidbody.data.linear_velocity.y - += (rigidbody.data.mass * rigidbody.data.gravity_scale - * gravity); - } - // Add damping - if (rigidbody.data.angular_velocity_coefficient > 0) { - rigidbody.data.angular_velocity - *= rigidbody.data.angular_velocity_coefficient; - } - if (rigidbody.data.linear_velocity_coefficient.x > 0 - && rigidbody.data.linear_velocity_coefficient.y > 0) { - rigidbody.data.linear_velocity - *= rigidbody.data.linear_velocity_coefficient; - } + if (transform.game_object_id == rigidbody.game_object_id) { + // Add gravity + if (rigidbody.data.gravity_scale > 0) { + rigidbody.data.linear_velocity.y + += (rigidbody.data.mass * rigidbody.data.gravity_scale + * gravity * dt); + } + // Add coefficient rotation + if (rigidbody.data.angular_velocity_coefficient > 0) { + rigidbody.data.angular_velocity + *= std::pow(rigidbody.data.angular_velocity_coefficient, dt); + + } - // Max velocity check - if (rigidbody.data.angular_velocity - > rigidbody.data.max_angular_velocity) { - rigidbody.data.angular_velocity - = rigidbody.data.max_angular_velocity; - } else if (rigidbody.data.angular_velocity - < -rigidbody.data.max_angular_velocity) { - rigidbody.data.angular_velocity - = -rigidbody.data.max_angular_velocity; - } + // Add coefficient movement horizontal + if (rigidbody.data.linear_velocity_coefficient.x > 0) + { + rigidbody.data.linear_velocity.x + *= std::pow(rigidbody.data.linear_velocity_coefficient.x, dt); + } - if (rigidbody.data.linear_velocity.x - > rigidbody.data.max_linear_velocity.x) { - rigidbody.data.linear_velocity.x - = rigidbody.data.max_linear_velocity.x; - } else if (rigidbody.data.linear_velocity.x - < -rigidbody.data.max_linear_velocity.x) { - rigidbody.data.linear_velocity.x - = -rigidbody.data.max_linear_velocity.x; - } + // Add coefficient movement horizontal + if (rigidbody.data.linear_velocity_coefficient.y > 0) + { + rigidbody.data.linear_velocity.y + *= std::pow(rigidbody.data.linear_velocity_coefficient.y, dt); + } - if (rigidbody.data.linear_velocity.y - > rigidbody.data.max_linear_velocity.y) { - rigidbody.data.linear_velocity.y - = rigidbody.data.max_linear_velocity.y; - } else if (rigidbody.data.linear_velocity.y - < -rigidbody.data.max_linear_velocity.y) { - rigidbody.data.linear_velocity.y - = -rigidbody.data.max_linear_velocity.y; - } + // Max velocity check + if (rigidbody.data.angular_velocity + > rigidbody.data.max_angular_velocity) { + rigidbody.data.angular_velocity + = rigidbody.data.max_angular_velocity; + } else if (rigidbody.data.angular_velocity + < -rigidbody.data.max_angular_velocity) { + rigidbody.data.angular_velocity + = -rigidbody.data.max_angular_velocity; + } + + // Set max velocity to maximum length + if(rigidbody.data.linear_velocity.length() > rigidbody.data.max_linear_velocity) { + rigidbody.data.linear_velocity.normalize(); + rigidbody.data.linear_velocity *= rigidbody.data.max_linear_velocity; + } - // Move object - if (!rigidbody.data.constraints.rotation) { - transform.rotation += rigidbody.data.angular_velocity; - transform.rotation = std::fmod(transform.rotation, 360.0); - if (transform.rotation < 0) { - transform.rotation += 360.0; - } - } - if (!rigidbody.data.constraints.x) { - transform.position.x += rigidbody.data.linear_velocity.x; - } - if (!rigidbody.data.constraints.y) { - transform.position.y += rigidbody.data.linear_velocity.y; + // Move object + if (!rigidbody.data.constraints.rotation) { + transform.rotation += rigidbody.data.angular_velocity * dt; + transform.rotation = std::fmod(transform.rotation, 360.0); + if (transform.rotation < 0) { + transform.rotation += 360.0; } } + if (!rigidbody.data.constraints.x) { + transform.position.x += rigidbody.data.linear_velocity.x * dt; + } + if (!rigidbody.data.constraints.y) { + transform.position.y += rigidbody.data.linear_velocity.y * dt; + } } break; case Rigidbody::BodyType::KINEMATIC: diff --git a/src/test/PhysicsTest.cpp b/src/test/PhysicsTest.cpp index 43d2931..4af34f5 100644 --- a/src/test/PhysicsTest.cpp +++ b/src/test/PhysicsTest.cpp @@ -27,7 +27,7 @@ public: .mass = 1, .gravity_scale = 1, .body_type = Rigidbody::BodyType::DYNAMIC, - .max_linear_velocity = vec2{10, 10}, + .max_linear_velocity = 10, .max_angular_velocity = 10, .constraints = {0, 0}, }); |