Où placer la logique de détection de collision?

19

Je développe un petit moteur de jeu 2D. Les personnages ont une méthode de peinture qui fait actuellement ce qui suit:

  1. Calculez la nouvelle position du personnage en fonction de sa vitesse, etc.
  2. Mettre à jour la cellule de la grille de collision **
  3. Dessinez le personnage à la nouvelle position

** J'ai créé une grille de collision pour réduire le nombre de contrôles d'intersection

Maintenant, l'algorithme de base que j'ai pensé pour détecter la collision est:

For Each Character
    Check intersection with characters in surrounding 8 cells

Je peux simplement placer ce code dans la méthode de peinture. Mais voici le problème que j'anticipe.

Supposons que deux caractères A et B se trouvent dans des cellules adjacentes de la grille de collision. Maintenant, selon l'algorithme ci-dessus dans l'itération du caractère A, il détectera qu'il est entré en collision avec B. Dans l'itération pour le caractère B, il détectera qu'il est entré en collision avec A.

Mais j'ai une idée que lorsque A détecte qu'il est entré en collision avec B, il doit informer B qu'il est entré en collision avec A. Cela permettrait d'économiser beaucoup de comparaisons lorsqu'il y a plus de 2 acteurs en collision. Mais je ne sais pas comment gérer cela. Je pense qu'au lieu que chaque personnage vérifie sa collision, je devrais vérifier la collision à l'intérieur de la boucle de jeu.

Cette approche serait-elle correcte? Comment avez-vous géré ce genre de problème? J'ai pensé au truc de la grille de collision moi-même. Existe-t-il des alternatives à la logique de grille de collision?

Biscuit salé
la source
Je suis désolé de nitpick, mais dans une bibliothèque spécialisée de physique 2D. La physique du jeu est généralement très approximative, donc toute solution qui ne rend pas le jeu non jouable est très bien, mais si vous voulez le résoudre correctement, utilisez simplement la physique spécialisée comme Box2D ... :-D
user712092

Réponses:

14

L'approche habituelle pour la détection des collisions consiste à ne pas détecter les collisions A ou B par elles-mêmes.

Au lieu de cela, vous déplacez d'abord tous les objets, puis un système de collision distinct recherche les collisions entre toutes les paires d'objets, informe chaque objet des choses avec lesquelles il est entré en collision, puis rend enfin tous les objets.

Donc, essentiellement, au lieu de "déplacer, vérifier les collisions, dessiner" à l'intérieur de votre fonction Paint (), vous divisez "déplacer" et "dessiner" en fonctions distinctes que vous appelez séparément (d'abord "déplacer" pour chaque objet, puis "dessiner" pour chaque objet). Et entre ceux-ci, vérifiez les collisions.

Remarque avancée: si l'un de vos objets se déplace en réaction aux collisions détectées, vous devrez peut-être répéter l'étape "Rechercher les collisions entre toutes les paires d'objets", au cas où la réponse à la collision d'un objet provoque une autre collision.

Trevor Powell
la source
C'est la bonne façon de faire les choses. Laissez les objets assumer leurs responsabilités et le système de collision devrait décider de ce qui se passe lorsqu'ils rencontrent un obstacle. Vous pouvez également avoir un rectangle / cylindre de collision (2d / 3d) autour de vos personnages comme une sorte de déclencheur précoce.
James P.
Génial! En ce qui concerne la note avancée, les collisions ne devraient-elles pas être revérifiées uniquement pour les objets qui se déplacent en réaction à la collision et les objets avec lesquels ils entrent en collision dans la nouvelle position? Il y aura une chaîne de contrôles mais cela évitera de vérifier la collision pour tous les objets.
Cracker
Comment gérer cela - gamedev.stackexchange.com/questions/13076/…
Cracker
1

Je lance une boucle pour tous mes personnages dans la boucle de jeu comme vous le dites.

La façon dont je le fais est avec un état sur chacun de mes personnages, donc si A et B entrent en collision pendant que A vérifie la collision, A et B sont définis pour frapper. au début de la boucle de B, il vérifie s'il est déjà atteint, si tel n'est pas le cas, id ne lance pas la boucle.

J'ai mis le code affect dans la boucle afin que toute action à entreprendre sur B se soit produite dans la boucle de A, donc il ne devrait pas y avoir de raison pour que B vérifie car cela gâcherait le résultat de la collision, cela peut être différent pour vous cependant .

Skeith
la source
Mais dans ce cas, lorsque A détecte une intersection avec B, B.hit sera défini sur true et donc B ne vérifiera AUCUNE intersection. Mais si un autre personnage C croise B, B ne le détectera pas?
Cracker
Désolé, j'ai compris. Puisque A ne coupe pas C, C.hit sera toujours faux. B ne vérifiera pas les collisions. Mais C vérifiera et transmettra à B qu'il y a une collision entre B et C. Cool!
Cracker
Mais je suppose que si tous les A, B et C se croisent, il y aurait un problème. A définira B.hit et C.hit sur true. B et C sauront qu'ils sont entrés en collision avec A. Mais puisque leur propriété de coup est vraie, ils ne vérifieront pas la collision. La collision entre B et C passera inaperçue.
Cracker
Vous pouvez vous faufiler dans une méthode similaire en plaçant chaque objet de collision viable dans une collection quelconque, puis en vérifiant uniquement la collision avec les éléments qui viennent après l'objet dans la collection. IE: A vérifie contre B, C, D; B vérifie vs C, D; C vérifie vs D.Chacun derrière n'a pas besoin d'être vérifié car il a déjà été vérifié depuis le tour de celui derrière. Pas aussi rapide que d'ignorer complètement la collision de l'élément, mais néanmoins utile.
Lunin