Correction corruption de données avec plus de 2 balles
This commit is contained in:
		
							parent
							
								
									201b99b24a
								
							
						
					
					
						commit
						b14953215b
					
				|  | @ -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 | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ | |||
| #define __PTF_COLLISION_HPP__ | ||||
| 
 | ||||
| #include <SFML/Graphics.hpp> | ||||
| #include <memory> | ||||
| 
 | ||||
| class Object; | ||||
| 
 | ||||
|  | @ -19,10 +20,10 @@ struct CollisionData { | |||
|     sf::Vector2f normal; | ||||
|     float depth; | ||||
| 
 | ||||
|     Object& obj_a; | ||||
|     Object& obj_b; | ||||
|     std::shared_ptr<Object> obj_a; | ||||
|     std::shared_ptr<Object> obj_b; | ||||
| 
 | ||||
|     CollisionData(Object& obj_a, Object& obj_b); | ||||
|     CollisionData(); | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  |  | |||
|  | @ -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é | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										11
									
								
								src/game.cpp
								
								
								
								
							
							
						
						
									
										11
									
								
								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 | ||||
|         ); | ||||
|     } | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -5,10 +5,12 @@ | |||
| #include <iostream> | ||||
| #include <memory> | ||||
| #include <fstream> | ||||
| #include <fenv.h> | ||||
| 
 | ||||
| int main() { | ||||
|     Manager manager; | ||||
|     std::shared_ptr<Menu> menu = std::shared_ptr<Menu>(new Menu(manager)); | ||||
|     feenableexcept(FE_ALL_EXCEPT & ~FE_INEXACT); | ||||
| 
 | ||||
|     try { | ||||
|         manager.setState(menu); | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ | |||
| #include "level.hpp" | ||||
| #include "constants.hpp" | ||||
| #include "collision.hpp" | ||||
| #include <iostream> | ||||
| #include <cmath> | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue