Cette question est une question "de suivi" de ma précédente, concernant la détection et la résolution des collisions, que vous pouvez trouver ici .
Si vous ne voulez pas lire la question précédente, voici une brève description du fonctionnement de mon moteur physique:
Chaque entité physique est stockée dans une classe appelée SSSPBody.
Seuls les AABB sont pris en charge.
Chaque SSSPBody est stocké dans une classe appelée SSSPWorld, qui met à jour chaque corps et gère la gravité.
À chaque image, SSSPWorld met à jour chaque corps.
Chaque corps mis à jour recherche les corps à proximité dans un hachage spatial, vérifie s'ils doivent détecter les collisions avec eux. Si oui, ils invoquent un événement "collision" et vérifient s'ils doivent résoudre les collisions avec eux. Si oui, ils calculent le vecteur de pénétration et le chevauchement directionnel, puis modifient leur position afin de résoudre la pénétration.
Lorsqu'un corps entre en collision avec un autre, il transfère sa vitesse à l'autre en réglant simplement la vitesse du corps à la sienne.
La vitesse d'un corps est définie sur 0 lorsqu'il n'a pas changé de position depuis la dernière image. S'il entre également en collision avec un corps en mouvement (comme un ascenseur ou une plate-forme mobile), il calcule la différence de mouvement de l'ascenseur pour voir si le corps n'a pas bougé de sa dernière position.
En outre, un corps invoque un événement "écrasé" lorsque tous ses coins AABB chevauchaient quelque chose dans un cadre.
Ceci est le code source COMPLET de mon jeu. Il est divisé en trois projets. SFMLStart est une bibliothèque simple qui gère la saisie, le dessin et la mise à jour des entités. SFMLStartPhysics est le plus important, où se trouvent les classes SSSPBody et SSSPWorld. PlatformerPhysicsTest est le projet de jeu, contenant toute la logique du jeu.
Et c'est la méthode « mise à jour » dans la classe SSSPBody, a commenté et simplifié. Vous ne pouvez y jeter un œil que si vous n'avez pas envie de regarder l'ensemble du projet SFMLStartSimplePhysics. (Et même si vous le faites, vous devriez toujours y jeter un œil car il est commenté.)
Le .gif montre deux problèmes.
- Si les corps sont placés dans un ordre différent, des résultats différents se produisent. Les caisses de gauche sont identiques aux caisses de droite, placées uniquement dans l'ordre inverse (dans l'éditeur).
- Les deux caisses doivent être propulsées vers le haut de l'écran. Dans la situation de gauche, aucune caisse n'est propulsée. À droite, un seul d'entre eux l'est. Les deux situations sont involontaires.
Premier problème: ordre de mise à jour
C'est assez simple à comprendre. Dans la situation de gauche, la caisse la plus haute est mise à jour avant l'autre. Même si la caisse du bas "transfère" la vitesse à l'autre, elle doit attendre la prochaine image pour se déplacer. Comme il n'a pas bougé, la vitesse de la caisse inférieure est réglée sur 0.
Je n'ai aucune idée de comment résoudre ce problème. Je préférerais que la solution ne dépende pas du "tri" de la liste de mise à jour, car je pense que je fais quelque chose de mal dans la conception du moteur physique.
Comment les principaux moteurs physiques (Box2D, Bullet, Chipmunk) gèrent-ils l'ordre de mise à jour?
Deuxième problème: une seule caisse est propulsée vers le plafond
Je ne comprends pas encore pourquoi cela se produit. Ce que fait l'entité "ressort" est de régler la vitesse du corps à -4000 et de la repositionner au-dessus du ressort lui-même. Même si je désactive le code de repositionnement, le problème persiste.
Mon idée est que lorsque la caisse inférieure entre en collision avec la caisse supérieure, sa vitesse est fixée à 0. Je ne sais pas pourquoi cela se produit.
Malgré la chance de ressembler à quelqu'un qui abandonne au premier problème, j'ai posté tout le code source du projet ci-dessus. Je n'ai rien pour le prouver, mais croyez-moi, j'ai essayé de résoudre ce problème, mais je n'ai tout simplement pas trouvé de solution et je n'ai aucune expérience préalable de la physique et des collisions. J'essaie de résoudre ces deux problèmes depuis plus d'une semaine et maintenant je suis désespéré.
Je ne pense pas que je puisse trouver une solution par moi-même sans retirer de nombreuses fonctionnalités du jeu (transfert de vitesse et ressorts, par exemple).
Merci beaucoup pour le temps passé à lire cette question, et merci encore plus si vous essayez de trouver une solution ou une suggestion.