II) Alexandre
 
 

1 Début de programmation dans le projet

Tout d’abord pour commencer, la première chose à faire fut le déplacement simple des unités selon 16 directions. Pour ce faire, il faut faire une recherche de la direction dans laquelle l’unité va se déplacer afin de sélectionner la portion d’image dans le fichier image de l’unité en déplacement qui sera à afficher à l’écran.
Par la suite, il faut changer les coordonnées des unités en fonction de leurs directions.
Une fois cette partie implémentée, une chose flagrante à l’œil survint : on ne voit pas le changement de directions des unités. Il a fallut décomposer l’algorithme de rotation des unités en 2 cas distincts à cause de la direction 0 qui faisait faire une rotation toujours dans le même sens.
 
 

2 Algorithme de cheminement

Comme les cartes sont divisées en tiles de 32 pixels, la recherche s’effectue au niveau des tiles. L’état des tiles est ‘walkable’ lorsque celui ci ne contient pas d’arbre ou de bâtiment sur sa surface. A partir du point de départ, on crée un arbre de recherche, cet arbre comporte 8 fils et garde le père du nœud pointé. Après beaucoup d’erreurs de pointeurs, et après m’être familiariser avec leur comportement la base fonctionnait plus ou moins correctement, avec quelques erreurs. Ma première idée fut le développement de A*, mais au lieu de faire une approximation au but je fais un calcul direct de la distance entre l’arrivée et le point actuellement en développement. L’algorithme développé se nomme ‘Best First’

ptrees = ^trees;
trees = record
  f0,f1,f2,f3,f4,f5,f6,f7 : ptrees;
  pere : ptrees;
  x,y : byte;
end;

ptree est l’arbre de recherche que l’on va développer, il contient donc 8 fils correspondants au tiles autour de celui que l’on développe, il garde le père du nœud pour faciliter le parcours de l’arbre pour le vider et comprend aussi les coordonnées du tile développé x et y.

pcoords = ^coords;
coords = record
  x,y : byte;
  suivant : pcoords;
  dist : longint;
  ptree : ptrees;
end;

pcoord est la liste des tiles ouverts, il contient les coordonnées, la distance jusqu’à l’arrivée afin de trier la liste chaînée de tiles. Le pcoord pointe sur l’arbre de recherche pour donner à la procédure Astar directement le nœud à développer.

maps = record
  walkable ,
  ecrit ,
  closed : Boolean;
  ptree : ptrees;
end;
support_maps = array [0..NTilesX-1,0..NTilesY-1] of maps;

searchmap prend des paramètres directement de BackTileMap(cf. I.7. L’Engin : The Next Generation) : walkable et plus tard closed de la carte sauvée par l’éditeur. Elle pointe aussi vers l’arbre, ceci sert lorsque l’on ne trouve pas de chemin, le booléen ecrit servira dans l’algorithme pour éviter de développer un tile de la carte déjà exploré.
 
 

Principe de la recherche :

On crée une liste de tiles ouverts (tiles explorés mais non développés).
On les trie par ordre croissant par rapport à la distance entre le nœud développé et l’arrivée.
Pour tous les tiles voisins du nœud développer,
                        S’il est ‘walkable’ et si ce tile n’a pas déjà été développé alors on crée un fils et on le met dans la liste des tiles ouverts.
On supprime le nœud qui vient d’être développé de la liste des tiles ouverts.

On réitère ces opérations jusqu’à ce que l’on trouve l’arrivée.
On renvoie à l’unité une liste chaînée de tiles qu’elle va franchir.
 
 

Voici une représentation graphique de l’algorithme Best First :



Une fois la base de l’algorithme implémentée, il restait des problèmes, 3 majeurs :
    -l’optimisation
    -pas de gestion de surfaces fermées
    -Impossible de cliquer sur un tile non ’walkable’
 
 

3 Optimisation

Au lieu de renvoyer une liste de tous les tiles à franchir, mieux vaut renvoyer une liste de points, où l’unité va changer de direction. Pour ce faire, j’ai effectué lors de la remontée de l’arbre de l’arrivée au point de départ de la recherche. Et seulement ensuite je vérifie dans cette liste les différences d’abscisses et d’ordonnées entre le tile précédent et le tile actuel avec le tile actuel avec le tile suivant. Les abscisses et les ordonnées sont converties en coordonnées en multipliant les tiles par leurs dimensions. Ceci permet aux unités de n’avoir que quelques points où elles doivent changer de directions. On renvoie une liste appelée pcoordonnée qui est attribuée à chaque unité.
 
 

4 Gestion des surfaces fermées

Définition de la surface fermée :
C’est une surface qui n’est pas accessible de l’extérieur
Ex : une île ou une colline

Les premières fois, il y avait des plantages lorsque l’on cliquait d’une surface ouverte vers une surface fermée car l’arbre se développait jusqu’à ce qu’elle soit bloquée et il ne trouvait jamais l’arrivée alors j’ai pensé qu’il fallait garder un pointeur sur l’élément le plus proche de l’arrivée dans l’arbre mais dans ce cas, toute la carte était développée cela rendait le jeu impossible car toute la carte était développée et il fallait pour cela attendre au moins 5 secondes.
Alors j’ai fait une recherche à partir de l’arrivée sachant qu’elle était sur une surface fermée, cette recherche s’effectuait en cercle concentrique autour de l’arrivée jusqu’à ce qu’il y ait un tile ‘walkable’, donc on changeait, l’arrivée.
Dans l’autre sens, si l’on essaie de déplacer une unité de la surface fermée vers la surface ouverte alors, on quitte lorsque l’unité ne puisse plus développer l’arbre et on garde le minimum.
Lorsque aucun changement de l’arrivée n’avait été fait, on obtenait :
 
 

Comme vous pouvez le voir, aucun chemin n’est trouvé.
L’algorithme recherche le premier tile ‘walkable’ autour de l’arrivée lorsque celui ci est une surface fermée .

Ex :


 
 

5 Pour cliquer sur un tile non ‘walkable’

On considère que tous les tiles non ‘walkable’ sont des surfaces fermées et ensuite on applique les algorithmes pour les surfaces fermées. Si l’on a une forêt dense où les unités ne peuvent pas entrer et que par malchance il y ait un tile ‘walkable’ alors on se retrouve dans une mauvaise position : toute la carte est développée.
 
 

6 Unités plus grandes qu’un soldat

Les soldats peuvent être comparés au niveau de leur taille a un tile tandis que les chars en représentent quatre. Lorsque l’on déplaçait un char, graphiquement il coupait les arbres. Il a donc fallut faire le même algorithme que le précédent avec quatre fois plus de vérifications. Donc il  ne faut même plus penser développer toute la carte car voir un moteur 2D rapide et ralentir le projet pour les déplacements n’est pas une chose envisageable. Les chars m’ont donc fait penser, par leurs agissements, à changer toute la technique de déplacement d’une surface ouvert vers une surface fermée.

7 Version finale

Au lieu de faire une recherche déjà longue en opérations pour trouver le point d’arrivée sur une surface fermée, l’algorithme garde le tile le plus proche de l’arrivée et lorsque l’on développe un tile qui s’éloigne par rapport au minimum on arrête la recherche.
Avant d’arriver à cette version beaucoup de problèmes sont survenus comme :
    -lorsque l’unité a fini de marcher, elle part tête baissée vers le point d’arrivée en traversant les surfaces fermées, les forêts, les rochers, et les bâtiments.
    -dans certaines directions le char commençait à aller sur les bases puis arriver à la quitter toujours dans la même direction, de même ils arrivaient à uitter                les surfaces fermées.