Réponse du rectangle de collision


10

J'ai des difficultés à faire entrer en collision un rectangle mobile avec plus d'un rectangle.

J'utilise SFML et il a une fonction pratique appelée intersectsqui prend 2 rectangles et renvoie les intersections. J'ai un vecteur plein de rectangles avec lesquels je veux que mon rectangle mobile entre en collision. Je passe en revue cela en utilisant le code suivant (p est le rectangle mobile).

IsCollidingWithrenvoie un booléen mais utilise également des SFML intersectspour déterminer les intersections.

while(unsigned i = 0; i!= testRects.size(); i++){
   if(p.IsCollidingWith(testRects[i]){
        p.Collide(testRects[i]);
   }
}

et le Collide()code réel :

void gameObj::collide( gameObj collidingObject ){

 printf("%f %f\n", this->colliderResult.width, this->colliderResult.height);

if (this->colliderResult.width < this->colliderResult.height) {
    // collided on X
    if (this->getCollider().left < collidingObject.getCollider().left ) {
        this->move( -this->colliderResult.width , 0);
    }else {
        this->move( this->colliderResult.width, 0 );
    }

}

if(this->colliderResult.width > this->colliderResult.height){
    if (this->getCollider().top < collidingObject.getCollider().top ) {
        this->move( 0, -this->colliderResult.height);
    }else {     
        this->move( 0, this->colliderResult.height );
    }

}

et le IsCollidingWith()code est:

bool gameObj::isCollidingWith( gameObj testObject ){
if (this->getCollider().intersects( testObject.getCollider(), this->colliderResult )) {
    return true;
}else {
    return false;
}

Cela fonctionne bien quand il n'y en a qu'un Rectdans la scène. Cependant, lorsqu'il y en a plus d'un, Rectcela provoque un problème lors de l'élaboration de 2 collisions à la fois.

Une idée de comment gérer cela correctement? J'ai téléchargé une vidéo sur YouTube pour montrer mon problème. La console à l'extrême droite montre la largeur et la hauteur des intersections. Vous pouvez voir sur la console qu'il essaie de calculer 2 collisions à la fois, je pense que c'est là que le problème est causé.

Enfin, l'image ci-dessous semble bien illustrer mon problème:

rectangle entrant en collision avec plusieurs autres rectangles


Le lien vidéo est rompu.
XiaoChuan Yu

Les colliderobjets retournés sont-ils this->getCollider()mis à jour par this->move()??
XiaoChuan Yu

Pourriez-vous ajouter plus d'informations s'il vous plaît? Quel est le problème exactement? La vidéo YouTube semble montrer un comportement prévisible, et il n'y a qu'un autre rectangle dans la scène.
Wackidev

Réponses:


3

Votre image illustre l'un des nombreux problèmes liés à l'utilisation de formes convexes - en particulier des rectangles - pour simuler une surface plane comme un sol. L'algorithme conduit à coincer les personnages sur les bords intérieurs des formes composant le sol.

Une solution simple consiste à vérifier la collision verticale uniquement, à corriger cela, puis à vérifier à nouveau la collision horizontale. À moins que vous ne tombiez et que vous n'essayiez de glisser le long d'un mur, auquel cas vous souhaitez d'abord vérifier les collisions horizontales. Comment savez-vous quand vérifier d'abord? Vous pouvez le faire en fonction de la composante de votre vitesse qui est la plus grande (si le mouvement horizontal est plus important, vérifiez d'abord les collisions verticales, sinon vérifiez les collisions horizontales).

Ce qui peut être encore plus simple - et plus performant - est de générer à la place une liste d'arêtes pour votre monde. Autrement dit, pour vos boîtes constituant le sol, définissez un indicateur indiquant que seul leur bord supérieur est réellement collidable, puis ignorez les collisions avec les autres bords. Vous ne pourrez pas utiliser la routine de collision de SFML pour cela, mais honnêtement, les collisions de boîtes sont probablement le code le plus simple que vous aurez jamais écrit dans un jeu. Cette technique fonctionne particulièrement bien si votre monde est aligné sur une grille. Je voudrais consulter les excellents tutoriels Metanet (http://www.metanetsoftware.com/technique.html/) pour cette technique.

Vous allez rencontrer de nombreux autres problèmes en essayant de créer un jeu de plateforme 2D simple comme vous. De loin, la meilleure ressource que j'ai vue en retard est la suivante, que vous devriez lire, puis relire:

http://higherorderfun.com/blog/2012/05/20/the-guide-to-implementing-2d-platformers/


1

Une solution simple serait peut-être de vérifier les collisions avec chaque rectangle et de reculer, dans la direction opposée du mouvement, jusqu'à ce qu'aucune collision ne soit détectée. Si cela résout le problème, la mise en œuvre devrait également être assez simple.


+1, j'ai en fait écrit à ce sujet ici: gamedev.stackexchange.com/questions/38252/…
Markus von Broady

0

Je ne pense pas que le calcul de 2 collisions soit un problème, mais uniquement un problème de performances. Pour que la collision soit correctement gérée, il peut être nécessaire de la tester deux fois. En utilisant votre diagramme, pensez que si A est testé contre B en premier, il devra également être testé contre les autres cases, et pourrait bien entrer en collision avec une autre.

J'espère que c'est utile?


0

Ce n'est pas vraiment une méthode optimale, vous devriez essayer de déterminer le moment le plus tôt ou le premier point le long du chemin des objets en mouvement où les collisions se produisent et déplacer les objets vers cette position (ou la position à l'heure calculée), en essayant de corriger en fonction des positions de pénétration après le mouvement est très problématique, mais vous pouvez utiliser votre processus actuel avec un petit changement. Continuez à vérifier les collisions jusqu'à ce qu'il n'y en ait pas.

bool collided = true;
while(collided) {
   collided = false
   while(unsigned i = 0; i!= testRects.size(); i++){
      if(p.IsCollidingWith(testRects[i]){
         collided = true
         p.Collide(testRects[i]);
      }
   }
}

Notez qu'il existe des situations où cela conduira à une boucle infinie (pensez à une situation où le déplacement de la boîte hors d'une collision entraîne une autre collection, et le déplacement de la boîte hors de cette collision la remet dans la même position de collision qu'avant)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.