From b14953215ba239c0ae3d2a887f4bc72bcb0a83dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Delabre?= Date: Sun, 10 Apr 2016 22:00:58 +0200 Subject: [PATCH] =?UTF-8?q?Correction=20corruption=20de=20donn=C3=A9es=20a?= =?UTF-8?q?vec=20plus=20de=202=20balles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/block.hpp | 2 +- include/collision.hpp | 7 ++++--- include/gravity_block.hpp | 2 +- include/object.hpp | 8 +++---- include/player.hpp | 2 +- src/block.cpp | 2 +- src/collision.cpp | 38 ++++++++++++++++----------------- src/game.cpp | 11 ++++++---- src/gravity_block.cpp | 2 +- src/main.cpp | 2 ++ src/object.cpp | 44 +++++++++++++++++++++------------------ src/player.cpp | 2 +- 12 files changed, 66 insertions(+), 56 deletions(-) diff --git a/include/block.hpp b/include/block.hpp index a22a056..92b70d9 100644 --- a/include/block.hpp +++ b/include/block.hpp @@ -58,7 +58,7 @@ public: /** * Appelé lorsque le bloc est activé par un objet */ - virtual void activated(Level& level, Object& object); + virtual void activated(Level& level, Object* object); /** * Récupère l'identifiant de type des blocs diff --git a/include/collision.hpp b/include/collision.hpp index 1f9978d..01d212d 100644 --- a/include/collision.hpp +++ b/include/collision.hpp @@ -2,6 +2,7 @@ #define __PTF_COLLISION_HPP__ #include +#include class Object; @@ -19,10 +20,10 @@ struct CollisionData { sf::Vector2f normal; float depth; - Object& obj_a; - Object& obj_b; + std::shared_ptr obj_a; + std::shared_ptr obj_b; - CollisionData(Object& obj_a, Object& obj_b); + CollisionData(); }; /** diff --git a/include/gravity_block.hpp b/include/gravity_block.hpp index b5c0949..403b1b3 100644 --- a/include/gravity_block.hpp +++ b/include/gravity_block.hpp @@ -42,7 +42,7 @@ public: /** * Appelé lorsque le bloc de gravité est activé par un objet */ - virtual void activated(Level& level, Object& object); + virtual void activated(Level& level, Object* object); /** * Récupère l'identifiant de type des blocs de gravité diff --git a/include/object.hpp b/include/object.hpp index 3270a8c..15be611 100644 --- a/include/object.hpp +++ b/include/object.hpp @@ -78,7 +78,7 @@ public: /** * Appelé lorsque l'objet est activé par un autre */ - virtual void activated(Level& level, Object& object) = 0; + virtual void activated(Level& level, Object* object) = 0; /** * Récupère l'identifiant de type de cet objet @@ -111,14 +111,14 @@ public: * Détecte s'il y a collision entre cet objet * et l'objet passé en paramètre */ - virtual bool detectCollision(const Object& obj, CollisionData& data) const; + virtual bool detectCollision(Object::Ptr obj, CollisionData& data) const; /** * Résolution de la collision entre cet objet * et l'objet passé en paramètre selon la normale * donnée */ - virtual void solveCollision(Level& level, Object& obj, const sf::Vector2f& normal); + virtual void solveCollision(Level& level, Object::Ptr obj, const sf::Vector2f& normal); /** * Application de la correction positionnelle sur @@ -128,7 +128,7 @@ public: * les objets peuvent accumuler une erreur de positionnement * qui les fait "plonger" les uns dans les autres */ - virtual void positionalCorrection(Object& obj, const sf::Vector2f& normal, float depth); + virtual void positionalCorrection(Object::Ptr obj, const sf::Vector2f& normal, float depth); /** * Récupère l'accélération de l'objet diff --git a/include/player.hpp b/include/player.hpp index 6381af3..db78397 100644 --- a/include/player.hpp +++ b/include/player.hpp @@ -57,7 +57,7 @@ public: /** * Appelé lorsque le joueur est activé par un objet */ - virtual void activated(Level& level, Object& object); + virtual void activated(Level& level, Object* object); /** * Récupère l'identifiant de type des joueurs diff --git a/src/block.cpp b/src/block.cpp index c2275c2..777a26e 100644 --- a/src/block.cpp +++ b/src/block.cpp @@ -71,7 +71,7 @@ void Block::draw(Level& level) { } } -void Block::activated(Level& level, Object& object) { +void Block::activated(Level& level, Object* object) { // ne rien faire si le bloc est activé. // Ceci est un bloc de base qui n'a pas a réagir // aux activations diff --git a/src/collision.cpp b/src/collision.cpp index 058eb4a..3a105f8 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -12,14 +12,14 @@ * un cercle et un rectangle */ bool circleToAABB(CollisionData& data) { - Object& circle = data.obj_a; - Object& aabb = data.obj_b; + Object::Ptr circle = data.obj_a; + Object::Ptr aabb = data.obj_b; // recherche du point le plus proche du centre du cercle // sur le rectangle. On regarde la position relative du cercle // par rapport au rectangle - sf::FloatRect box = aabb.getAABB(); - sf::Vector2f relpos = aabb.getPosition() - circle.getPosition(); + sf::FloatRect box = aabb->getAABB(); + sf::Vector2f relpos = aabb->getPosition() - circle->getPosition(); sf::Vector2f closest = relpos; // on restreint la position relative pour rester @@ -70,12 +70,12 @@ bool circleToAABB(CollisionData& data) { // si le cercle est à l'extérieur et que la normale est plus // longue que son rayon, il n'y a pas collision - if (!is_inside && squared_length >= circle.getRadius() * circle.getRadius()) { + if (!is_inside && squared_length >= circle->getRadius() * circle->getRadius()) { return false; } float length = std::sqrt(squared_length); - data.depth = circle.getRadius() - length; + data.depth = circle->getRadius() - length; if (length != 0) { data.normal = prenormal / length; @@ -94,7 +94,7 @@ bool circleToAABB(CollisionData& data) { */ bool AABBToCircle(CollisionData& data) { // la collision rectangle -> cercle est la collision cercle -> rectangle - Object& transfer = data.obj_b; + Object::Ptr transfer = data.obj_b; data.obj_b = data.obj_a; data.obj_a = transfer; @@ -106,12 +106,12 @@ bool AABBToCircle(CollisionData& data) { * deux cercles */ bool circleToCircle(CollisionData& data) { - Object& circle_a = data.obj_a; - Object& circle_b = data.obj_b; + Object::Ptr circle_a = data.obj_a; + Object::Ptr circle_b = data.obj_b; - sf::Vector2f dir = circle_b.getPosition() - circle_a.getPosition(); + sf::Vector2f dir = circle_b->getPosition() - circle_a->getPosition(); float squared_length = dir.x * dir.x + dir.y * dir.y; - float total_radius = circle_b.getRadius() + circle_a.getRadius(); + float total_radius = circle_b->getRadius() + circle_a->getRadius(); // si les deux cercles sont à une distance supérieure // à la somme de leurs deux rayons, il n'y a pas eu collision @@ -141,12 +141,12 @@ bool circleToCircle(CollisionData& data) { * deux rectangles */ bool AABBToAABB(CollisionData& data) { - Object& aabb_a = data.obj_a; - Object& aabb_b = data.obj_b; + Object::Ptr aabb_a = data.obj_a; + Object::Ptr aabb_b = data.obj_b; - sf::FloatRect box_a = aabb_a.getAABB(); - sf::FloatRect box_b = aabb_b.getAABB(); - sf::Vector2f relpos = aabb_b.getPosition() - aabb_a.getPosition(); + sf::FloatRect box_a = aabb_a->getAABB(); + sf::FloatRect box_b = aabb_b->getAABB(); + sf::Vector2f relpos = aabb_b->getPosition() - aabb_a->getPosition(); float overlap_x = box_a.width / 2 + box_b.width / 2 - std::abs(relpos.x); float overlap_y = box_a.height / 2 + box_b.height / 2 - std::abs(relpos.y); @@ -194,10 +194,10 @@ std::map< {std::make_pair(CollisionType::AABB, CollisionType::CIRCLE), AABBToCircle} }; -CollisionData::CollisionData(Object& obj_a, Object& obj_b) : obj_a(obj_a), obj_b(obj_b) {} +CollisionData::CollisionData() {} bool getCollisionData(CollisionData& data) { return collision_map[std::make_pair( - data.obj_a.getCollisionType(), - data.obj_b.getCollisionType() + data.obj_a->getCollisionType(), + data.obj_b->getCollisionType() )](data); } diff --git a/src/game.cpp b/src/game.cpp index fbedf84..859e043 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -122,9 +122,12 @@ void Game::update() { for (unsigned int j = i + 1; j < objects.size(); j++) { Object::Ptr obj_b = objects[j]; - CollisionData data(*obj_a, *obj_b); + CollisionData data; - if (obj_a->detectCollision(*obj_b, data)) { + data.obj_a = obj_a; + data.obj_b = obj_b; + + if (obj_a->detectCollision(obj_b, data)) { colliding.push_back(data); } } @@ -138,7 +141,7 @@ void Game::update() { // résolution des collisions détectées for (unsigned int i = 0; i < colliding.size(); i++) { CollisionData& collided = colliding[i]; - collided.obj_a.solveCollision(*this, collided.obj_b, collided.normal); + collided.obj_a->solveCollision(*this, collided.obj_b, collided.normal); } // intégration de la vitesse dans la position @@ -149,7 +152,7 @@ void Game::update() { // application de la correction positionnelle for (unsigned int i = 0; i < colliding.size(); i++) { CollisionData& collided = colliding[i]; - collided.obj_a.positionalCorrection( + collided.obj_a->positionalCorrection( collided.obj_b, collided.normal, collided.depth ); } diff --git a/src/gravity_block.cpp b/src/gravity_block.cpp index 0df611d..80fe85e 100644 --- a/src/gravity_block.cpp +++ b/src/gravity_block.cpp @@ -39,7 +39,7 @@ void GravityBlock::beforeDraw(Level& level) { ); } -void GravityBlock::activated(Level& level, Object& object) { +void GravityBlock::activated(Level& level, Object* object) { Block::activated(level, object); // lorsque le bloc est activé, il transmet son diff --git a/src/main.cpp b/src/main.cpp index 02147a3..be54796 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,10 +5,12 @@ #include #include #include +#include int main() { Manager manager; std::shared_ptr menu = std::shared_ptr(new Menu(manager)); + feenableexcept(FE_ALL_EXCEPT & ~FE_INEXACT); try { manager.setState(menu); diff --git a/src/object.cpp b/src/object.cpp index b670972..59e6f98 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -2,6 +2,7 @@ #include "level.hpp" #include "constants.hpp" #include "collision.hpp" +#include #include const unsigned int Object::PROP_MASS = 1; @@ -197,32 +198,32 @@ void Object::updatePosition() { position += velocity * Manager::FRAME_TIME.asSeconds(); } -bool Object::detectCollision(const Object& obj, CollisionData& data) const { +bool Object::detectCollision(Object::Ptr obj, CollisionData& data) const { // si les objets ne sont pas sur la même couche, // ils ne peuvent pas entrer en collision - if (getLayer() != obj.getLayer()) { + if (getLayer() != obj->getLayer()) { return false; } // si les deux boîtes englobantes des deux objets ne // s'intersectent pas, il ne risque pas d'y avoir de collision - if (!getAABB().intersects(obj.getAABB())) { + if (!getAABB().intersects(obj->getAABB())) { return false; } return getCollisionData(data); } -void Object::solveCollision(Level& level, Object& obj, const sf::Vector2f& normal) { +void Object::solveCollision(Level& level, Object::Ptr obj, const sf::Vector2f& normal) { // si les deux objets sont de masse infinie, réinitialisation // des vitesses en tant que collision - if (getMassInvert() == 0 && obj.getMassInvert() == 0) { + if (getMassInvert() == 0 && obj->getMassInvert() == 0) { setVelocity(sf::Vector2f(0, 0)); - obj.setVelocity(sf::Vector2f(0, 0)); + obj->setVelocity(sf::Vector2f(0, 0)); return; } - sf::Vector2f rel_velo = obj.getVelocity() - getVelocity(); + sf::Vector2f rel_velo = obj->getVelocity() - getVelocity(); float dot_normal = rel_velo.x * normal.x + rel_velo.y * normal.y; // si les directions sont divergentes, pas besoin @@ -233,24 +234,24 @@ void Object::solveCollision(Level& level, Object& obj, const sf::Vector2f& norma // en ce point, on est bertins qu'une collision a eu lieu. // activation réciproque des deux objets - activated(level, obj); - obj.activated(level, *this); + activated(level, obj.get()); + obj->activated(level, this); // on utilise le plus petit coefficient de friction entre les // deux objets comme le coefficient de la collision - float restitution = std::min(getRestitution(), obj.getRestitution()); + float restitution = std::min(getRestitution(), obj->getRestitution()); // calcule et applique l'impulsion de résolution de la collision float collision_impulse = -(1.f + restitution) * std::min(dot_normal + .8f, 0.f) / - (getMassInvert() + obj.getMassInvert()); + (getMassInvert() + obj->getMassInvert()); setVelocity(getVelocity() - getMassInvert() * collision_impulse * normal); - obj.setVelocity(obj.getVelocity() + obj.getMassInvert() * collision_impulse * normal); + obj->setVelocity(obj->getVelocity() + obj->getMassInvert() * collision_impulse * normal); // application des forces de frottement entre les deux objets // on calcule le vecteur tangent qui porte la force de frottement. // les coefficients de friction utilisés sont les moyennes de ceux des deux objets - rel_velo = obj.getVelocity() - getVelocity(); + rel_velo = obj->getVelocity() - getVelocity(); dot_normal = rel_velo.x * normal.x + rel_velo.y * normal.y; sf::Vector2f tangent = rel_velo - dot_normal * normal; @@ -265,9 +266,9 @@ void Object::solveCollision(Level& level, Object& obj, const sf::Vector2f& norma tangent /= tangent_length; float magnitude = -(rel_velo.x * tangent.x + rel_velo.y * tangent.y) / - (getMassInvert() + obj.getMassInvert()); - float static_friction = (getStaticFriction() + obj.getStaticFriction()) / 2.f; - float dynamic_friction = (getDynamicFriction() + obj.getDynamicFriction()) / 2.f; + (getMassInvert() + obj->getMassInvert()); + float static_friction = (getStaticFriction() + obj->getStaticFriction()) / 2.f; + float dynamic_friction = (getDynamicFriction() + obj->getDynamicFriction()) / 2.f; float friction_impulse; // utilisation de la loi de Coulomb sur les frottements dynamiques/statiques @@ -279,16 +280,16 @@ void Object::solveCollision(Level& level, Object& obj, const sf::Vector2f& norma } setVelocity(getVelocity() - getMassInvert() * friction_impulse * tangent); - obj.setVelocity(obj.getVelocity() + obj.getMassInvert() * friction_impulse * tangent); + obj->setVelocity(obj->getVelocity() + obj->getMassInvert() * friction_impulse * tangent); } -void Object::positionalCorrection(Object& obj, const sf::Vector2f& normal, float depth) { +void Object::positionalCorrection(Object::Ptr obj, const sf::Vector2f& normal, float depth) { float position_correction = std::max(depth - Constants::CORRECTION_SLOP, 0.0f) / - (getMassInvert() + obj.getMassInvert()) * + (getMassInvert() + obj->getMassInvert()) * Constants::CORRECTION_PERCENTAGE; setPosition(getPosition() - getMassInvert() * position_correction * normal); - obj.setPosition(obj.getPosition() + obj.getMassInvert() * position_correction * normal); + obj->setPosition(obj->getPosition() + obj->getMassInvert() * position_correction * normal); } sf::Vector2f Object::getAcceleration() const { @@ -338,6 +339,9 @@ float Object::getMassInvert() const { } void Object::setMass(float set_mass) { + if (getTypeId() == 1){ + std::cout << "Change mass player from " << mass << " to " << set_mass << std::endl; + } mass = set_mass; inv_mass = -1.f; } diff --git a/src/player.cpp b/src/player.cpp index 45f9944..00b8306 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -89,7 +89,7 @@ void Player::draw(Level& level) { level.getWindow().draw(sprite); } -void Player::activated(Level& level, Object& object) { +void Player::activated(Level& level, Object* object) { // ne rien faire si le joueur est activé. // en règle générale, c'est l'objet activé par le joueur // qui s'occupe de la réponse