From 578d950ec749edfd9390b408f2dba3c3c3b942a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Delabre?= Date: Mon, 11 Apr 2016 12:34:43 +0200 Subject: [PATCH] Quelques optimisations --- include/block.hpp | 1 + src/block.cpp | 20 +++++++++++++------ src/collision.cpp | 34 ++++++++++++++++---------------- src/game.cpp | 49 +++++++++++++++++++++-------------------------- src/object.cpp | 14 +++++++++++--- 5 files changed, 64 insertions(+), 54 deletions(-) diff --git a/include/block.hpp b/include/block.hpp index ed71f85..d8c2394 100644 --- a/include/block.hpp +++ b/include/block.hpp @@ -14,6 +14,7 @@ private: protected: mutable sf::Sprite sprite; + sf::FloatRect aabb; /** * Initialisation des propriétés du bloc donné diff --git a/src/block.cpp b/src/block.cpp index 3159af9..3f63f75 100644 --- a/src/block.cpp +++ b/src/block.cpp @@ -6,7 +6,15 @@ const unsigned int Block::TYPE_ID = 2; -Block::Block() : Object() {} +Block::Block() : Object() { + aabb = sf::FloatRect( + -Constants::GRID / 2, + -Constants::GRID / 2, + Constants::GRID, + Constants::GRID + ); +} + Block::~Block() {} Object::Ptr Block::clone() const { @@ -77,11 +85,11 @@ void Block::kill(Game& game) { } sf::FloatRect Block::getAABB() const { - return sf::FloatRect( - getPosition().x - Constants::GRID / 2, - getPosition().y - Constants::GRID / 2, - Constants::GRID, Constants::GRID - ); + sf::FloatRect transl_aabb = aabb; + transl_aabb.left += getPosition().x; + transl_aabb.top += getPosition().y; + + return transl_aabb; } float Block::getRadius() const { diff --git a/src/collision.cpp b/src/collision.cpp index 3a105f8..ba29403 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -180,24 +180,22 @@ bool AABBToAABB(CollisionData& data) { return true; } -/** - * Dictionnaire associant les types impliqués - * dans une collision à leur fonction de résolution - */ -std::map< - std::pair, - std::function -> collision_map = { - {std::make_pair(CollisionType::CIRCLE, CollisionType::CIRCLE), circleToCircle}, - {std::make_pair(CollisionType::CIRCLE, CollisionType::AABB), circleToAABB}, - {std::make_pair(CollisionType::AABB, CollisionType::AABB), AABBToAABB}, - {std::make_pair(CollisionType::AABB, CollisionType::CIRCLE), AABBToCircle} -}; - CollisionData::CollisionData() {} bool getCollisionData(CollisionData& data) { - return collision_map[std::make_pair( - data.obj_a->getCollisionType(), - data.obj_b->getCollisionType() - )](data); + CollisionType type_a = data.obj_a->getCollisionType(); + CollisionType type_b = data.obj_b->getCollisionType(); + + if (type_a == CollisionType::CIRCLE && type_b == CollisionType::CIRCLE) { + return circleToCircle(data); + } + + if (type_a == CollisionType::CIRCLE && type_b == CollisionType::AABB) { + return circleToAABB(data); + } + + if (type_a == CollisionType::AABB && type_b == CollisionType::CIRCLE) { + return AABBToCircle(data); + } + + return AABBToAABB(data); } diff --git a/src/game.cpp b/src/game.cpp index 9d4b340..d58fc4b 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -127,22 +127,21 @@ void Game::update() { pending_kill.empty(); - // détection des objets déplaçables en dehors de la zone de jeu - for (auto it = objects.begin(); it != objects.end(); it++) { - if (!isInZone(*it) && (*it)->getMass() != 0) { - // l'objet est sorti de la zone, on le signale et on - // planifie sa mort à la prochaine frame - (*it)->kill(*this); - pending_kill.push_back(*it); - } - } - // détection des objets en collision - for (unsigned int i = 0; i < objects.size(); i++) { - Object::Ptr obj_a = objects[i]; + for (auto it = objects.begin(); it != objects.end(); it++) { + Object::Ptr obj_a = *it; - for (unsigned int j = i + 1; j < objects.size(); j++) { - Object::Ptr obj_b = objects[j]; + // l'objet est sorti de la zone, on le signale et on + // planifie sa mort à la prochaine frame + if (!isInZone(obj_a) && obj_a->getMass() != 0) { + obj_a->kill(*this); + pending_kill.push_back(obj_a); + } + + // on regarde s'il est en collision avec + // d'autres objets + for (auto jt = it + 1; jt != objects.end(); jt++) { + Object::Ptr obj_b = *jt; CollisionData data; data.obj_a = obj_a; @@ -154,28 +153,24 @@ void Game::update() { } } - // intégration des forces dans la vitesse (seconde moitié) - for (unsigned int i = 0; i < objects.size(); i++) { - objects[i]->updateVelocity(*this); + // intégration des forces dans la vitesse + for (auto it = objects.begin(); it != objects.end(); it++) { + (*it)->updateVelocity(*this); } // 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); + for (auto it = colliding.begin(); it != colliding.end(); it++) { + it->obj_a->solveCollision(*this, it->obj_b, it->normal); } // intégration de la vitesse dans la position - for (unsigned int i = 0; i < objects.size(); i++) { - objects[i]->updatePosition(); + for (auto it = objects.begin(); it != objects.end(); it++) { + (*it)->updatePosition(); } // application de la correction positionnelle - for (unsigned int i = 0; i < colliding.size(); i++) { - CollisionData& collided = colliding[i]; - collided.obj_a->positionalCorrection( - collided.obj_b, collided.normal, collided.depth - ); + for (auto it = colliding.begin(); it != colliding.end(); it++) { + it->obj_a->positionalCorrection(it->obj_b, it->normal, it->depth); } } diff --git a/src/object.cpp b/src/object.cpp index 0e20870..12e7b5c 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -204,6 +204,14 @@ bool Object::detectCollision(Object::Ptr obj, CollisionData& data) const { return false; } + // si on a affaire à deux objets de masse infinie et + // de vitesse nulle, pas de collision + if (getMassInvert() == 0 && obj->getMassInvert() == 0 && + getVelocity().x == 0 && getVelocity().y == 0 && + obj->getVelocity().x == 0 && obj->getVelocity().y == 0) { + 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())) { @@ -252,9 +260,9 @@ void Object::solveCollision(Level& level, Object::Ptr obj, const sf::Vector2f& n // les coefficients de friction utilisés sont les moyennes de ceux des deux objets 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; - float tangent_length = std::sqrt(tangent.x * tangent.x + tangent.y * tangent.y); + float tangent_length = tangent.x * tangent.x + tangent.y * tangent.y; // la tangente est nulle : pas de frottement à générer // on évite ainsi une division par zéro @@ -262,7 +270,7 @@ void Object::solveCollision(Level& level, Object::Ptr obj, const sf::Vector2f& n return; } - tangent /= tangent_length; + tangent /= std::sqrt(tangent_length); float magnitude = -(rel_velo.x * tangent.x + rel_velo.y * tangent.y) / (getMassInvert() + obj->getMassInvert());