J'ai écrit un jeu RTS (une démo pour un moteur de jeu en quelque sorte) dans lequel l'interaction de base de l'utilisateur avec le jeu consiste à sélectionner un groupe de soldats, puis à cliquer avec le bouton droit sur la carte pour les déplacer vers l'emplacement spécifié. C'est en JavaScript et vous pouvez jouer avec ici ( code ).
Ignorant le problème de la façon dont les soldats se déplacent de leur emplacement actuel vers leur destination, ma question est de déterminer quelle est leur destination réelle. Voici ce que j'ai essayé jusqu'à présent:
- Tentative 1: dites à tous les soldats sélectionnés de se déplacer vers les coordonnées sur lesquelles la souris a cliqué. Cela a le comportement étrange que tous les soldats iront ensuite autour de la cible de manière anormale.
- Tentative 2: Trouvez les coordonnées moyennes de tous les soldats sélectionnés, puis trouvez le décalage à partir de ce point central pour chaque soldat, et enfin traduisez ce décalage autour des coordonnées de la souris. Cela fonctionne très bien, sauf que si vos soldats sélectionnés sont très éloignés, ils ne se rapprocheront pas de la cible.
- Tentative 3: Construisez une grille autour des coordonnées de la souris et placez chaque soldat sélectionné dans une cellule de la grille. Si chaque soldat arrive dans sa cellule assignée, cela fonctionne très bien. Cependant, les soldats sont affectés à des cellules de la grille dans l'ordre de leur apparition, donc parfois ils entrent en collision (c'est-à-dire que tous les soldats du côté droit essaieront d'aller vers le côté gauche), ce qui ne semble pas naturel.
- Tentative 4: utilisez une grille comme précédemment, mais triez d'abord les soldats par emplacement de manière à ce qu'ils s'alignent de manière sensible, c'est-à-dire que si vous avez cliqué en dessous du groupe, les soldats en bas du groupe se retrouveront au bas de la grille lorsqu'ils atteindre leur destination. Cela fonctionne plutôt bien, mais il y a parfois des problèmes et je ne sais pas pourquoi.
Voici la fonction qui détermine les coordonnées de destination:
function moveSelectedSoldiersToMouse() {
var w = 0, h = 0, selected = [];
// Get information about the selected soldiers.
myTeam.soldiers.forEach(function(soldier) {
if (soldier.selected) {
selected.push(soldier);
w += soldier.width;
h += soldier.height;
}
});
var numSelected = selected.length, k = -1;
if (!numSelected) return;
// Build a grid of evenly spaced soldiers.
var sqrt = Math.sqrt(numSelected),
rows = Math.ceil(sqrt),
cols = Math.ceil(sqrt),
x = Mouse.Coords.worldX(),
y = Mouse.Coords.worldY(),
iw = Math.ceil(w / numSelected), // grid cell width
ih = Math.ceil(h / numSelected), // grid cell height
wg = iw*1.2, // width of gap between cells
hg = ih*1.2; // height of gap between cells
if ((rows-1)*cols >= numSelected) rows--;
w = iw * cols + wg * (cols-1); // total width of group
h = ih * rows + hg * (rows-1); // total height of group
// Sort by location to avoid soldiers getting in each others' way.
selected.sort(function(a, b) {
// Round to 10's digit; specific locations can be off by a pixel or so
var ax = a.x.round(-1), ay = a.y.round(-1), bx = b.x.round(-1), by = b.y.round(-1);
return ay - by || ax - bx;
});
// Place the grid over the mouse and send soldiers there.
for (var i = 0; i < rows; i++) {
for (var j = 0; j < cols; j++) {
var s = selected[++k];
if (s) {
var mx = x + j * (iw+wg) - w * 0.5 + s.width * 0.5,
my = y + i * (ih+hg) - h * 0.5 + s.height * 0.5;
// Finally, move to the end destination coordinates
s.moveTo(mx, my);
}
}
}
}
Vous pouvez coller cette fonction dans la console JavaScript de votre navigateur lors de la visualisation de la démo et jouer avec elle pour changer le comportement des soldats.
Ma question est la suivante: existe-t-il une meilleure façon de déterminer l'emplacement cible de chaque soldat vers lequel se déplacer?
la source
Réponses:
Voici mes suggestions sur vos idées:
Tentative 1: pour corriger cette situation, vous pouvez implémenter l'idée "assez proche" évoquée par Spencer. Je ferais quelque chose comme dessiner une bulle autour du point final, qui grandit en fonction d'un rapport entre le nombre et la taille des unités qui s'y trouvent déjà. Supposons que la bulle commence à la taille d'une unité, puis lorsque la première arrive, le rayon double pour les deux unités suivantes, etc.
Tentative 2: un correctif pour celui-ci consisterait à prendre la distance moyenne du groupe les uns par rapport aux autres, puis à réduire la distance des valeurs aberrantes à cela, de sorte que le groupe se retrouve plus groupé qu'il ne l'était à l'origine (la métrique pourrait être plus courte / plus long que la moyenne, tout ce qui le rend décent, ou définissez éventuellement une taille de formulaire maximale basée sur le nombre / la taille des troupes) La seule chose dont vous auriez à vous soucier est lorsque vous modifiez le chemin d'une valeur aberrante, vous '' Je dois vérifier et m'assurer que cela n'interfère pas avec les autres chemins
Tentative 3: vous avez amélioré celle-ci lors de la tentative 4
Tentative 4: Des sons comme celui-ci fonctionneraient bien si vous rencontrez des problèmes. Je recommanderais de jouer avec des spahs autres qu'une simple formation de grille, cependant, pour rendre le mouvement un peu plus naturel, sauf si vous optez pour un réalisme / style militaire, auquel cas il pourrait être intéressant de les avoir "formées" "avant de bouger, mais cela pourrait devenir ennuyeux pour le joueur après un certain temps.
La tentative 4 semble la plus proche de la suppression du comportement de fraisage dans votre problème, mais en termes de maintien du mouvement sans aucun ajustement autre que ce qui est nécessaire, mon préféré serait probablement la tentative 2.
Mais en tant que solution complètement différente, vous pouvez avoir deux types d'objets en ce qui concerne la recherche de chemin; chaque unité, ainsi qu'un objet "escouade" invisible.
Escouade - Vous construisez l'objet escouade au centre du groupe, comme les autres solutions, et utilisez votre orientation pour le diriger vers l'objectif.
Unités - Les unités ignorent complètement le but, et utilisent à la place le pathfinding pour rester à une certaine distance (ou formation, ou toute autre métrique finit par rendre le mouvement le meilleur) de l'objet de l'escouade.
Cela sépare les différents aspects de la recherche de chemin et vous permet de modifier chaque côté isolément pour plus de contrôle sur son apparence.
la source
La tentative 3 pourrait fonctionner, mais elle a besoin d'un peu de raffinement.
Pensez au concept d'une formation (votre grille est un début). Une formation doit avoir un emplacement (c.-à-d. Les coordonnées du clic ou le soldat / bâtiment cible) et une rotation (cela peut être fixe, aléatoire ou déterministe). La formation doit avoir le même nombre de postes que le nombre de soldats sélectionnés.
Un exemple simple de formation peut être un cercle autour de la cible. L'espace se positionne également autour et augmente le rayon du cercle pour s'adapter à tous les soldats sans entrer en collision.
Le problème suivant est de décider quel soldat marche vers quelle position dans la formation. Une solution simple pourrait être d'amener chaque soldat à se déplacer vers la position la plus proche de lui. Si celui-ci est déjà «choisi» par un autre soldat, prenez la prochaine position la plus proche, etc.
Les formations peuvent devenir assez intéressantes. Ci-dessous, une image de la «formation de corne de taureau» utilisée avec grand succès par Shaka le Zoulou . (L'image provient du module de formation TotalWar )
la source
Lors du clic de l'utilisateur, tracez un vecteur de chaque soldat à l'emplacement cliqué. Obtenez l'angle vectoriel moyen à partir des vecteurs dessinés pour chaque soldat et déplacez chaque soldat de la longueur de son vecteur individuel dans cette direction avec le même angle. Cela devrait donner l'apparence des unités se déplaçant en formation jusqu'au point et devrait empêcher les unités de s'agglutiner.
Si vous voulez que les unités quittent la formation, vous pouvez pointer l'angle de chaque soldat directement à l'emplacement cliqué. Cependant, sans collision, les unités commenceront à converger. Pour contrer cela, ajoutez une collision et forcez les unités à cesser de bouger une fois qu'elles sont "assez proches" du point cliqué. Les premières unités à arriver seront exactement sur le point et les dernières à arriver devraient être ordonnées d'arrêter de bouger une fois qu'elles sont suffisamment proches ou qu'un certain laps de temps s'est écoulé.
Vous pouvez calculer la longueur du chemin et la vitesse de l'unité pour déterminer quand une seule unité doit arriver, puis forcer l'unité à s'arrêter si elle dépasse ce temps d'une certaine quantité. Vous devrez jouer un peu avec ce numéro.
la source