Quelques optimisations

This commit is contained in:
Mattéo Delabre 2016-04-11 12:34:43 +02:00
parent 405456d2b1
commit 578d950ec7
5 changed files with 64 additions and 54 deletions

View File

@ -14,6 +14,7 @@ private:
protected:
mutable sf::Sprite sprite;
sf::FloatRect aabb;
/**
* Initialisation des propriétés du bloc donné

View File

@ -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 {

View File

@ -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<CollisionType, CollisionType>,
std::function<bool(CollisionData&)>
> 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);
}

View File

@ -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);
}
}

View File

@ -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());