Dans le monde naturel, les organismes manifestent certains comportements lorsqu'ils voyagent en groupe. Ce phénomène, également appelé flocage, se produit à des échelles microscopiques (bactéries) et macroscopiques (poissons). En utilisant des ordinateurs, ces modèles peuvent être simulés en créant des règles simples et en les combinant. Ceci est connu comme comportement émergent, et peut être utilisé dans des jeux pour simuler un mouvement de groupe chaotique ou réaliste.
Remarque: Bien que ce tutoriel soit écrit en utilisant Flash et AS3, vous devriez pouvoir utiliser les mêmes techniques et concepts dans presque tous les environnements de développement de jeux..
Dans ce tutoriel, je couvrirai les trois règles principales utilisées pour simuler le flocage et expliquerai comment les implémenter. Avant de commencer, voici une terminologie que je vais utiliser:
Cette démo montre les effets des trois règles de flocage que je vais expliquer dans ce tutoriel: alignement, cohésion, et séparation.
Le code source complet de cette démo peut être téléchargé ici. Cet article ne fera donc que souligner les aspects les plus importants de la mise en œuvre. N'hésitez pas à télécharger la source si vous souhaitez en savoir plus.
L'alignement est un comportement qui oblige un agent particulier à s'aligner sur des agents proches..
Tout d'abord, nous allons créer une fonction qui prend un agent et renvoie un vecteur de vitesse.
fonction publique computeAlignment (myAgent: Agent): Point
Nous aurons besoin de deux variables: une pour stocker le vecteur que nous allons calculer, et une autre pour garder une trace du nombre de voisins de l'agent.
var v: Point = nouveau Point (); var neighbourCount = 0;
Avec nos variables initialisées, nous parcourons maintenant tous les agents et trouvons ceux qui se trouvent dans la liste. rayon du voisin - c'est-à-dire ceux qui sont suffisamment proches pour être considérés comme des voisins de l'agent spécifié. Si un agent est trouvé dans le rayon, sa vitesse est ajoutée au vecteur de calcul et le nombre de voisins est incrémenté..
pour chaque (var agent: Agent dans agentArray) if (agent! = monAgent) if (monAgent.distanceFrom (agent) < 300) v.x += agent.velocity.x; v.y += agent.velocity.y; neighborCount++;
Si aucun voisin n'a été trouvé, nous renvoyons simplement le vecteur zéro (la valeur par défaut du vecteur de calcul).
if (neighbourCount == 0) renvoie v;
Enfin, on divise le vecteur de calcul par le nombre de voisins et on le normalise (on le divise par sa longueur pour obtenir un vecteur de longueur 1
), obtention du vecteur résultant final.
v.x / = neighbourCount; v.y / = neighbourCount; v.normaliser (1); retourner v;
La cohésion est un comportement qui amène les agents à se diriger vers le "centre de masse", c'est-à-dire la position moyenne des agents dans un certain rayon..
L'implémentation est presque identique à celle du comportement d'alignement, mais il existe quelques différences clés. Tout d'abord, au lieu d'ajouter le rapidité au vecteur de calcul, le position est ajouté à la place.
v.x + = agent.x; v.y + = agent.y;
Comme précédemment, le vecteur de calcul est divisé par le nombre de voisins, ce qui donne la position correspondant au centre de masse. Cependant, nous ne voulons pas le centre de masse lui-même, nous voulons la direction vers le centre de masse, nous recalculons donc le vecteur en tant que distance entre l'agent et le centre de masse. Enfin, cette valeur est normalisée et renvoyée.
v.x / = neighbourCount; v.y / = neighbourCount; v = nouveau point (v.x - myAgent.x, v.y - myAgent.y); v.normaliser (1); retourner v;
La séparation est le comportement qui force un agent à s'éloigner de tous ses voisins..
La mise en œuvre de la séparation est très similaire à celle de l'alignement et de la cohésion, je ne ferai donc que souligner ce qui est différent. Lorsqu'un agent voisin est trouvé, la distance entre l'agent et le voisin est ajoutée au vecteur de calcul..
v.x + = agent.x - myAgent.x; v.y + = agent.y - myAgent.y
Le vecteur de calcul est divisé par le nombre de voisins correspondant, mais avant la normalisation, une étape cruciale est impliquée. Le vecteur calculé doit être annulé pour que l'agent s'éloigne correctement de ses voisins..
v.x * = -1; v.y * = -1;
Une fois que ces trois règles ont été mises en œuvre, elles doivent être réunies. La manière la plus simple de procéder est la suivante:
var alignement = computeAlignment (agent); var cohésion = computeCohesion (agent); var separation = computeSeparation (agent); agent.velocity.x + = alignement.x + cohésion.x + séparation.x; agent.velocity.y + = alignement.y + cohésion.y + séparation.y; agent.velocity.normalize (AGENT_SPEED);
Ici, je calcule simplement les trois règles pour un agent particulier et les ajoute à la vélocité. Je normalise ensuite la vitesse puis multiplie par une constante représentant la vitesse par défaut d'un agent. Il est possible de l'améliorer davantage en ajoutant des poids pour chaque règle afin de modifier les comportements:
agent.velocity.x + = Alignement.x * AlignementWeight + Cohésion.x * CohesionWeight + separation.x * SeparationWeight; agent.velocity.y + = Alignement.y * AlignementWeight + Cohesion.y * CohesionWeight + separation.y * SeparationWeight;
La modification de ces poids changera la façon dont les agents s'assemblent. Veillez à expérimenter les chiffres jusqu'à ce que vous trouviez quelque chose que vous aimez..
Voici à nouveau la démo pour que vous puissiez l'essayer:
Le flocage est simple à mettre en œuvre, mais il a des résultats puissants. Le flocage peut s'avérer utile si vous faites un jeu avec une IA, en particulier de grands groupes d'IA qui interagissent les uns avec les autres. Utilisez-le bien.