J'ai récemment essayé la physique des cordes et j'ai découvert que la solution "standard" - fabriquer une corde à partir d'une série d'objets attachés avec des ressorts ou des articulations - n'était pas satisfaisante. Surtout lorsque le balancement de la corde est pertinent pour le jeu. Je ne m'inquiète pas vraiment de la capacité d'une corde à s'enrouler ou à s'affaisser (cela peut être simulé pour des effets visuels).
Pour le jeu, l’important est la capacité de la corde à s’enrouler dans l’environnement puis à se dérouler par la suite. Il ne doit même pas se comporter comme une corde - un "fil" composé de segments de droite ferait l'affaire. Voici une illustration:
Ceci est très similaire à la "corde Ninja" du jeu Worms.
Comme j'utilise un moteur physique 2D, mon environnement est constitué de polygones convexes 2D. (Plus précisément, j'utilise SAT dans Farseer.)
Ma question est donc la suivante: comment implémenteriez-vous l’effet "wrapping"?
Il semble assez évident que le fil sera constitué d’une série de segments de ligne qui se "scindent" et "se joignent". Et le dernier segment (actif) de cette ligne, où l'objet en mouvement se fixe, sera un joint de longueur fixe.
Mais quels sont les calculs / algorithmes utilisés pour déterminer quand et où le segment de ligne actif doit être fractionné? Et quand doit-il être rejoint avec le segment précédent?
(Auparavant, cette question concernait également le fait de procéder de la sorte dans un environnement dynamique - j'ai décidé de scinder cette question en d'autres questions.)
la source
Cela fait longtemps que je n’ai pas joué à Worms, mais si je me souviens bien, lorsque la corde s'enroule autour de lui, il n’ya qu’une section de corde (droite) en mouvement à la fois. Le reste de la corde devient statique
Donc, il y a très peu de physique réelle impliquée. La section active peut être modélisée comme un seul ressort rigide avec une masse à l'extrémité
Le bit intéressant sera la logique pour séparer / joindre des sections inactives de la corde à / de la section active.
J'imagine qu'il y aurait 2 opérations principales:
'Split' - La corde a coupé quelque chose. Divisez-le à l'intersection en une section inactive et la nouvelle section active plus courte
«Rejoindre» - La corde active s'est déplacée dans une position où l'intersection la plus proche n'existe plus (il peut s'agir simplement d'un simple test de produit angle / point?). Rejoin 2 sections, créant une nouvelle section plus longue et active
Dans une scène construite à partir de polygones 2D, tous les points de partage doivent se situer à un sommet du maillage de collision. La détection de collision peut simplifier les choses: «Si la corde passe au-dessus d'un sommet lors de cette mise à jour, divisez / joignez la corde à ce sommet?
la source
Découvrez comment la corde de ninja à Gusanos a été mise en œuvre:
Extrait pertinent de ninjarope.cpp :
la source
Je crains de ne pas pouvoir vous donner un algorithme concret, mais je me rends compte qu'il n'y a que deux choses qui importent pour détecter une collision avec la corde ninja: tous les sommets potentiellement en collision sur des obstacles. dans un rayon de la dernière "division" égal à la longueur restante du segment; et le sens de rotation actuel (dans le sens des aiguilles d'une montre ou dans le sens inverse). Si vous avez créé une liste temporaire d'angles du sommet "divisé" vers chacun des sommets voisins, votre algorithme doit simplement se soucier de savoir si votre segment est sur le point de dépasser cet angle pour un sommet donné. Si c'est le cas, vous devez effectuer une opération de division, ce qui est simple comme bonjour. Il s'agit simplement d'une ligne allant du dernier sommet fractionné à la nouvelle division, puis un nouveau reste est calculé.
Je pense que seuls les sommets comptent. Si vous êtes sur le point de frapper un segment entre des sommets sur un obstacle, alors votre détection de collision normale pour le gars accroché au bout de la corde devrait se déclencher. En d'autres termes, votre corde ne va jamais "accrocher" coins de toute façon, donc les segments entre peu importe.
Désolé, je n'ai rien de concret, mais j'espère que cela vous mènera là où vous devez être, conceptuellement, pour que cela se produise. :)
la source
Voici un article qui contient des liens vers des articles sur des types de simulations similaires (dans des contextes d'ingénierie / universitaires plutôt que pour des jeux): https://gamedev.stackexchange.com/a/10350/6398
J'ai essayé au moins deux approches différentes de détection de collision + réponse pour ce type de simulation "en fil" (comme dans le jeu Umihara Kawase); du moins, je pense que c'est ce que vous recherchez - il ne semble pas exister de terme spécifique pour ce type de simulation, j'ai plutôt tendance à l'appeler "fil" plutôt que "corde" car il semble que la plupart des gens Considérons que "corde" est synonyme de "chaîne de particules". Et, si vous voulez le comportement insaisissable de la corde ninja (c’est-à-dire qu’elle peut pousser ET tirer), il s’agit plus d’un fil rigide que d’une corde. En tous cas..
La réponse de Pekuja est bonne, vous pouvez implémenter la détection de collision continue en résolvant le moment où la zone signée des trois points est 0.
(Je ne peux pas me rappeler complètement OTOH mais vous pouvez l’approcher comme suit: trouvez le temps t où le point a est contenu dans la ligne passant par b, c, (je pense que j’ai fait cela en résolvant pour quand dot (ab, cb) = 0 pour trouver les valeurs de t), puis avec un temps valide 0 <= t <1, trouve la position paramétrique s de a sur le segment bc, c'est-à-dire a = (1-s) b + s c et si a est compris entre b et c (c'est-à-dire si 0 <= s <= 1) c'est une collision valide.
AFAICR, vous pouvez aussi l’approcher dans l’inverse (c’est-à-dire résoudre le problème et ensuite le brancher pour le trouver), mais c’est beaucoup moins intuitif. (Je suis désolé si cela n’a aucun sens, je n’ai pas le temps de fouiller dans mes notes et cela fait quelques années!)
Ainsi, vous pouvez maintenant calculer toutes les heures auxquelles des événements se produisent (par exemple, les nœuds de corde doivent être insérés ou supprimés); traiter l'événement le plus ancien (insérer ou supprimer un nœud), puis répéter / recurse jusqu'à ce qu'il n'y ait plus d'événements entre t = 0 et t = 1.
Un avertissement à propos de cette approche: si les objets que la corde peut enrouler sont dynamiques (surtout si vous les simulez ET leurs effets sur la corde, et inversement), il peut y avoir des problèmes si ces objets se coupent ou passent entre eux. autre - le fil peut devenir emmêlé. Et il sera certainement difficile d’empêcher ce type d’interaction / mouvement (les coins d’objets se glissant les uns dans les autres) dans une simulation physique de style box2d. Dans ce contexte, une faible pénétration entre les objets constitue un comportement normal.
(Du moins .. c'était un problème avec l'une de mes implémentations de "wire".)
Une solution différente, beaucoup plus stable mais qui omet certaines collisions dans certaines conditions, consiste simplement à utiliser des tests statiques (c’est-à-dire, ne vous préoccupez pas de la chronologie, divisez simplement chaque segment en collision au fur et à mesure que vous les trouvez), ce qui peut être beaucoup plus robuste - le fil ne s'emmêlera pas dans les coins et une petite pénétration suffira.
Je pense que l'approche de Pekuja fonctionne pour cela aussi, cependant il existe des approches alternatives. Une approche que j’ai utilisée consiste à ajouter des données de collision auxiliaires: à chaque sommet convexe v du monde (c.-à-d. Les coins des formes que la corde peut enrouler), ajoutez un point u formant le segment de droite dirigé uv, où u est un pointez "dans le coin" (c'est-à-dire dans le monde, "derrière" v; pour calculer u, vous pouvez projeter un rayon vers l'intérieur à partir de v le long de sa normale interpolée et vous arrêter quelque part après v ou avant que le rayon ne se croise avec une arête du monde et quitte la région solide ou vous pouvez simplement peindre manuellement les segments dans le monde à l’aide d’un éditeur / outil visuel).
Quoi qu'il en soit, vous avez maintenant un ensemble de "linesegs de coin" uv; pour chaque uv et chaque segment ab du fil, vérifiez si les intersections ab et uv (par exemple, une requête d'intersection linéaire, booléenne lineseg-lineseg); si c'est le cas, recurse (divise le lineseg ab en av et vb, c.-à-d. insère v), en enregistrant dans quelle direction la corde est courbée en v. est le même que lorsque b a été généré (tous ces tests de "direction de pliage" ne sont que des tests de zone signée); sinon, fusionnez les deux segments en un courant alternatif (c.-à-d. supprimez b).
Ou peut-être que j'ai fusionné et que je me suis séparé, j'oublie - mais cela fonctionne définitivement dans au moins un des deux ordres possibles! :)
Avec tous les segments de fil calculés pour le cadre actuel, vous pouvez alors simuler une contrainte de distance entre les deux extrémités du fil (et vous pouvez même impliquer les points intérieurs, c'est-à-dire les points de contact entre le fil et le monde, mais c'est un peu plus compliqué. )
Quoi qu'il en soit, j'espère que cela vous sera utile ... les articles de l'article que je vous ai lié devraient également vous donner quelques idées.
la source
Une approche consiste à modéliser la corde en particules collables, reliées par des ressorts. (assez raides, peut-être même comme un os à la place). Les particules entrent en collision avec l'environnement, s'assurant que la corde s'enroule autour des objets.
Voici une démo avec source: http://www.ewjordan.com/rgbDemo/
(Déplacez-vous vers la droite au premier niveau, il y a une corde rouge avec laquelle vous pouvez interagir)
la source