Création d'un dragueur de mines hexagonal

Ce que vous allez créer

Dans ce tutoriel, je vais essayer d’introduire le monde intéressant des jeux hexagonaux basés sur des tuiles en utilisant la plus simple des approches. Vous apprendrez à convertir les données d'un tableau bidimensionnel en une disposition de niveau hexagonal correspondante à l'écran et inversement. En utilisant les informations obtenues, nous allons créer un jeu de dragueur de mines hexagonal dans deux configurations hexagonales différentes..

Cela vous permettra de commencer à explorer de simples jeux de société hexagonaux et de jeux de réflexion et constituera un bon point de départ pour apprendre des approches plus complexes, telles que les systèmes de coordonnées hexagonaux axiaux ou cubiques..

1. Carreaux Hexagonaux et Layouts

Dans la génération actuelle de jeux occasionnels, nous ne voyons pas beaucoup de jeux utilisant une approche hexagonale basée sur les tuiles. Ceux que nous rencontrons sont généralement des jeux de réflexion, des jeux de société ou des jeux de stratégie. En outre, la plupart de nos besoins sont satisfaits par l’approche par grille carrée ou par approche isométrique. Cela conduit à la question naturelle: "Pourquoi avons-nous besoin d'une approche hexagonale différente et évidemment compliquée?" Découvrons-le.

Avantages de l'approche hexagonale

En quoi l’approche hexagonale basée sur les carreaux est-elle pertinente, puisque d’autres approches ont déjà été apprises et perfectionnées? Laissez-moi énumérer certaines des raisons.

  • Plus petit nombre de tuiles voisines: Comparé à une grille carrée, qui aura huit tuiles voisines, une tuile hexagonale n'aura que six voisins. Cela réduit les calculs pour des algorithmes compliqués.
  • Toutes les tuiles voisines sont à la même distance: pour une grille carrée, les quatre voisins diagonaux sont plus éloignés que les voisins horizontaux ou verticaux. Le fait que les voisins soient à égale distance est un grand soulagement lorsque nous calculons une heuristique et réduit les frais généraux liés à l'utilisation de deux méthodes différentes pour calculer quelque chose en fonction du voisin..
  • Unicité: De nos jours, des millions de jeux occasionnels sortent et se disputent le temps du joueur. Les grands jeux ne parviennent pas à attirer un public, et l'unique chose qui peut être garantie pour attirer l'attention d'un joueur est l'unicité. Un jeu utilisant une approche hexagonale se démarquera visuellement du jeu et semblera plus intéressant pour un public ennuyé par tous les mécanismes de jeu classiques.. 

Je dirais que la dernière raison devrait être suffisante pour que vous maîtrisiez cette nouvelle approche. Ajouter cet élément de jeu unique à votre logique de jeu peut faire toute la différence et vous permettre de faire un grand jeu.. 

Les autres raisons sont purement techniques et n'entrent en vigueur que lorsque vous utilisez des algorithmes complexes ou des ensembles de pavés plus volumineux. Il existe de nombreux autres aspects qui peuvent également être énumérés comme des avantages de l'approche hexagonale, mais la plupart dépendront de l'intérêt personnel du joueur..

Layouts

Un hexagone est un polygone à six côtés et un hexagone dont tous les côtés ont la même longueur est appelé un hexagone régulier. Pour des raisons théoriques, nous considérerons nos carreaux hexagonaux comme des hexagones réguliers, mais ils pourraient être écrasés ou allongés dans la pratique.. 

La chose intéressante est qu’un hexagone peut être placé de deux manières différentes: les coins pointus peuvent être alignés verticalement ou horizontalement. Lorsque les pointes sont alignées verticalement, on parle de horizontal mise en page, et quand ils sont alignés horizontalement, on l'appelle un verticale disposition. Vous pensez peut-être que les noms sont des noms erronés par rapport à l'explication fournie. Ce n'est pas le cas car la dénomination n'est pas basée sur les coins pointus mais sur la manière dont une grille de tuiles est disposée. L'image ci-dessous montre les différents alignements de tuiles et les dispositions correspondantes.

Le choix de la disposition dépend entièrement des visuels et du gameplay de votre jeu. Cependant, votre choix ne s'arrête pas là, car chacune de ces dispositions peut être mise en œuvre de deux manières différentes..

Considérons une disposition de grille hexagonale horizontale. Les lignes alternatives de la grille doivent être décalées horizontalement de hexTileWidth / 2. Cela signifie que nous pourrions choisir de décaler les lignes impaires ou les lignes paires. Si nous affichons également le correspondant rangée, colonne valeurs, ces variantes ressembleraient à l'image ci-dessous.

De même, la disposition verticale pourrait être mise en œuvre en deux variantes tout en compensant les colonnes alternatives par hexTileHeight / 2 comme indiqué ci-dessous.

2. Mise en œuvre des dispositions hexagonales

A partir de là, commencez à vous référer au code source fourni avec ce tutoriel pour une meilleure compréhension.

Les images ci-dessus, avec les lignes et les colonnes affichées, facilitent la visualisation d'une corrélation directe avec un tableau à deux dimensions qui stocke les données de niveau. Disons que nous avons un tableau simple à deux dimensions levelData comme ci-dessous.

var levelData = [[0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0 ], [0,0,0,0,0]]

Pour faciliter la visualisation, je vais montrer ici le résultat souhaité sous forme de variations verticales et horizontales..

Commençons par la disposition horizontale, qui est l'image sur le côté gauche. Dans chaque ligne, pris individuellement, les tuiles voisines sont décalées horizontalement de hexTileWidth. Les lignes alternatives sont décalées horizontalement d’une valeur de hexTileWidth / 2. La différence de hauteur verticale entre chaque rangée est hexTileHeight * 3/4

Pour comprendre comment nous sommes arrivés à une telle valeur pour le décalage de hauteur, nous devons prendre en compte le fait que les parties triangulaires supérieure et inférieure d'un hexagone disposé horizontalement sont exactement hexTileHeight / 4

Cela signifie que l'hexagone a un rectangle hexTileHeight / 2 partie au milieu, un triangle hexTileHeight / 4 partie sur le dessus, et un triangle inversé hexTileHeight / 4 partie sur le fond. Cette information est suffisante pour créer le code nécessaire pour tracer la grille hexagonale à l'écran.

var verticalOffset = hexTileHeight * 3/4; var horizontalOffset = hexTileWidth; var startX; var startY; var startXInit = hexTileWidth / 2; var startYInit = hexTileHeight / 2; var hexTile; pour (var i = 0; i < levelData.length; i++)  if(i%2!==0) startX=2*startXInit; else startX=startXInit;  startY=startYInit+(i*verticalOffset); for (var j = 0; j < levelData[0].length; j++)  if(levelData[i][j]!=-1) hexTile= new HexTile(game, startX, startY, 'hex',false,i,j,levelData[i][j]); hexGrid.add(hexTile);  startX+=horizontalOffset;  

Avec le HexTile prototype, j’ai ajouté quelques fonctionnalités supplémentaires au Phaser.Sprite prototype qui lui permet d'afficher la je et j valeurs. Le code place essentiellement une nouvelle tuile hexagonale Lutin à startX et début. Ce code peut être modifié pour afficher la variante même offset en supprimant simplement un opérateur dans la liste. si condition comme ceci: si (i% 2 === 0).

Pour une disposition verticale (l’image sur la moitié droite), les tuiles voisines de chaque colonne sont décalées verticalement de hexTileHeight. Chaque colonne de remplacement est décalée verticalement de hexTileHeight / 2. En appliquant la logique que nous avons appliquée pour le décalage vertical pour la disposition horizontale, nous pouvons voir que le décalage horizontal pour la disposition verticale entre les tuiles voisines d'une ligne est hexTileWidth * 3/4. Le code correspondant est ci-dessous.

var verticalOffset = hexTileHeight; var horizontalOffset = hexTileWidth * 3/4; var startX; var startY; var startXInit = hexTileWidth / 2; var startYInit = hexTileHeight / 2; var hexTile; pour (var i = 0; i < levelData.length; i++)  startX=startXInit; startY=2*startYInit+(i*verticalOffset); for (var j = 0; j < levelData[0].length; j++)  if(j%2!==0) startY=startY+startYInit; else startY=startY-startYInit;  if(levelData[i][j]!=-1) hexTile= new HexTile(game, startX, startY, 'hex', true,i,j,levelData[i][j]); hexGrid.add(hexTile);  startX+=horizontalOffset;  

De la même manière que pour la disposition horizontale, nous pouvons passer à la variante même offset en supprimant simplement la ! opérateur en haut si état. J'utilise un Phaser Groupe pour collecter tous les hexTiles nommé hexGrid. Pour des raisons de simplicité, j'utilise le point central de l'image hexagonale en mosaïque comme point d'ancrage. Sinon, nous devrons également tenir compte des décalages d'image.. 

Une chose à noter est que les valeurs de largeur et de hauteur de mosaïque dans la disposition horizontale ne sont pas égales à celles de largeur et de hauteur de mosaïque dans la disposition verticale. Mais si vous utilisez la même image pour les deux mises en page, il vous suffit de faire pivoter l'image de mosaïque de 90 degrés et d'échanger les valeurs de largeur et de hauteur de mosaïque..

3. Trouver l'indice de matrice d'une tuile hexagonale

La logique de placement de l'écran à l'écran était simple, mais l'inverse n'est pas si facile. Considérez que nous devons trouver l’indice de tableau de la tuile hexagonale sur laquelle nous avons tapé. Le code pour y parvenir n’est pas beau et on y parvient généralement par essais et erreurs.. 

Si nous considérons la disposition horizontale, il peut sembler que la partie rectangulaire centrale de la tuile hexagonale peut facilement nous aider à comprendre la j comme il s’agit simplement de diviser le X valeur par hexTileWidth et en prenant la valeur entière. Mais à moins de connaître le je valeur, nous ne savons pas si nous sommes sur une ligne impaire ou paire. Une valeur approximative de je peut être trouvé en divisant la valeur y par hexTileHeight * 3/4

Viennent maintenant les parties compliquées du carreau hexagonal: les parties triangulaires supérieure et inférieure. L'image ci-dessous nous aidera à comprendre le problème.

Les régions 2, 3, 5, 6, 8 et 9 forment ensemble une tuile. La partie la plus compliquée consiste à déterminer si la position taraudée est en 1/2 ou 3/4 ou 7/8 ou 9/10. Pour cela, nous devons examiner toutes les régions triangulaires individuelles et les comparer en utilisant la pente du bord incliné.. 

Cette pente peut être trouvée à partir de la hauteur et de la largeur de chaque région triangulaire, qui sont respectivement hexTileHeight / 4 et hexTileWidth / 2. Laissez-moi vous montrer la fonction qui fait cela.

fonction findHexTile () var pos = game.input.activePointer.position; pos.x- = hexGrid.x; pos.y- = hexGrid.y; var xVal = Math.floor ((pos.x) / hexTileWidth); var yVal = Math.floor ((pos.y) / (hexTileHeight * 3/4)); var dX = (pos.x)% hexTileWidth; var dY = (pos.y)% (hexTileHeight * 3/4); var pente = (hexTileHeight / 4) / (hexTileWidth / 2); var caldY = dX * pente; var delta = hexTileHeight / 4-caldY; if (yVal% 2 === 0) // la correction doit être effectuée par portions triangulaires et les lignes de décalage if (Math.abs (delta)> dY) if (delta> 0) // rangée impaire en bas à droite moitié xVal--; yVal--;  else // rang impair en bas à gauche moitié yVal--;  else if (dX> hexTileWidth / 2) // les valeurs disponibles ne fonctionnent pas même rangée en bas à droite si (dY<((hexTileHeight/2)-caldY))//even row bottom right half yVal--;  else if(dY>caldY) // rangs impairs en haut à droite et au milieu à droite moitiés xVal--;  else // même ligne en bas à gauche moitié yVal--;  pos.x = yVal; pos.y = xVal; retour pos; 

Tout d'abord, nous trouvons xVal et yVal de la même manière que nous le ferions pour une grille carrée. On trouve ensuite l’horizontale restante (dX) et vertical (dY) les valeurs après la suppression du décalage du multiplicateur de tuiles. En utilisant ces valeurs, nous essayons de déterminer si le point se trouve dans l'une des régions triangulaires compliquées. 

Si trouvé, nous apportons les modifications correspondantes aux valeurs initiales de xVal et yVal. Comme je l’ai dit plus tôt, le code n’est ni beau ni simple. La meilleure façon de comprendre cela serait d’appeler findHexTile avec la souris, puis mettez console.log dans chacune de ces conditions et déplacez la souris sur différentes régions dans une tuile hexagonale. De cette façon, vous pouvez voir comment chaque région intra-hexagonale est traitée.

Les changements de code pour la disposition verticale sont indiqués ci-dessous.

fonction findHexTile () var pos = game.input.activePointer.position; pos.x- = hexGrid.x; pos.y- = hexGrid.y; var xVal = Math.floor ((pos.x) / (hexTileWidth * 3/4)); var yVal = Math.floor ((pos.y) / (hexTileHeight)); var dX = (pos.x)% (hexTileWidth * 3/4); var dY = (pos.y)% (hexTileHeight); var pente = (hexTileHeight / 2) / (hexTileWidth / 4); var caldX = dY / pente; var delta = hexTileWidth / 4-caldX; if (xVal% 2 === 0) if (dX> Math.abs (delta)) // même à gauche else // impair impair si (delta> 0) // impair inférieur droit xVal--; yVal--;  else // impair droite en haut xVal--;  else if (delta> 0) if (dX

4. Trouver des voisins

Maintenant que nous avons trouvé la tuile sur laquelle nous avons tapé, trouvons les six tuiles voisines. C'est un problème très facile à résoudre une fois que nous avons analysé visuellement la grille. Considérons la disposition horizontale.

L'image ci-dessus montre l'intrus et le pair rangées d'une grille hexagonale disposée horizontalement quand une tuile du milieu a la valeur de 0 pour les deux je et j. À partir de l'image, il devient clair que si la ligne est impaire, alors pour une tuile à je, j les voisins sont je, j-1, i-1, j-1, i-1, j, je, j + 1, i + 1, j, et i + 1, j-1. Quand la ligne est paire, alors pour une tuile à je, j les voisins sont je, j-1i-1, ji-1, j + 1je, j + 1i + 1, j + 1, et i + 1, j. Cela pourrait être calculé manuellement facilement.

Analysons une image similaire pour les impairs et les pairs des colonnes d'une grille hexagonale alignée verticalement.

Lorsque nous avons une colonne impaire, une tuile à je, j aura je, j-1i-1, j-1, i-1, j, i-1, j + 1, je, j + 1, et i + 1, j en tant que voisins. De même, pour une colonne paire, les voisins sont i + 1, j-1, je, j-1, i-1, j, je, j + 1, i + 1, j + 1, et i + 1, j

5. Démineur hexagonal

Avec les connaissances ci-dessus, nous pouvons essayer de créer un jeu de dragueur de mines hexagonal dans deux configurations différentes. Décomposons les fonctionnalités d'un jeu de démineur.

  1. Il y aura un nombre N de mines cachées dans la grille.
  2. Si nous tapons sur une tuile avec une mine, le jeu est terminé.
  3. Si nous tapons sur une tuile qui a une mine voisine, elle affichera le nombre de mines tout autour.
  4. Si nous exploitons une mine sans mines voisines, cela conduirait à la révélation de toutes les tuiles connectées qui n'ont pas de mines.
  5. Nous pouvons appuyer et tenir pour marquer une tuile comme une mine.
  6. Le jeu est terminé lorsque nous révélons toutes les tuiles sans mines.

Nous pouvons facilement stocker une valeur dans le levelData tableau pour indiquer une mine. La même méthode peut être utilisée pour renseigner la valeur des mines voisines sur l'index de la matrice des tuiles voisines. 

Au début du jeu, nous allons peupler au hasard les levelData tableau avec N nombre de mines. Après cela, nous mettrons à jour les valeurs pour toutes les tuiles voisines. Nous allons utiliser une méthode récursive pour révéler en chaîne toutes les tuiles vierges connectées lorsque le joueur tape sur une tuile qui n'a pas de mine en tant que voisin.

Niveau de données

Nous devons créer une jolie grille hexagonale, comme le montre l'image ci-dessous..

Cela peut être fait en affichant seulement une partie de la levelData tableau. Si on utilise -1 comme valeur pour une tuile non utilisable et 0 comme valeur pour une tuile utilisable, notre levelData pour atteindre le résultat ci-dessus ressemblera à ceci.

// niveau de la dalle horizontale var levelData = [[-1, -1, -1,0,0,0,0,0,0,0,0, -1, -1, -1], [-1, -1 , 0,0,0,0,0,0,0,0, -1, -1, -1], [-1, -1,0,0,0,0,0,0,0,0, 0, -1, -1], [-1,0,0,0,0,0,0,0,0,0,0, -1, -1], [-1,0,0,0, 0,0,0,0,0,0,0,0, -1], [0,0,0,0,0,0,0,0,0,0,0,0, -1], [ 0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0, 0, -1], [-1,0,0,0,0,0,0,0,0,0,0,0, -1], [-1,0,0,0,0,0, 0,0,0,0,0, -1, -1], [-1, -1,0,0,0,0,0,0,0,0,0,0, -1, -1], [ -1, -1,0,0,0,0,0,0,0,0, -1, -1, -1], [-1, -1, -1,0,0,0,0, 0,0,0, -1, -1, -1]];

En boucle dans le tableau, nous n’ajouterions que des carreaux hexagonaux lorsque le levelData a une valeur de 0. Pour l'alignement vertical, le même levelData peut être utilisé, mais nous aurions besoin de transposer le tableau. Voici une méthode astucieuse qui peut le faire pour vous.

levelData = transpose (levelData); //… fonction transpose (a) return Object.keys (a [0]). Map (fonction (c) return a.map (fonction (r) return r [c];);); 

Ajouter des mines et mettre à jour les voisins

Par défaut, notre levelData a seulement deux valeurs, -1 et 0, dont nous n'utiliserions que la zone avec 0. Pour indiquer qu'une tuile contient une mine, on peut utiliser la valeur de dix

Une tuile hexagonale vierge peut avoir un maximum de six mines à proximité, car elle a six tuiles voisines. Nous pouvons également stocker ces informations dans la levelData une fois que nous avons ajouté toutes les mines. Essentiellement, un levelData indice ayant une valeur de dix a une mine, et si elle contient des valeurs de 0 à 6, cela indique le nombre de mines voisines. Après avoir rempli les mines et mis à jour les voisins, si un élément de tableau est toujours 0, il indique qu'il s'agit d'une tuile vierge sans mines voisines. 

Nous pouvons utiliser les méthodes suivantes pour nos besoins.

fonction addMines () var tileType = 0; var tempArray = []; var newPt = new Phaser.Point (); pour (var i = 0; i < levelData.length; i++)  for (var j = 0; j < levelData[0].length; j++)  tileType=levelData[i][j]; if(tileType===0) newPt=new Phaser.Point(); newPt.x=i; newPt.y=j; tempArray.push(newPt);    for (var i = 0; i < numMines; i++)  newPt=Phaser.ArrayUtils.removeRandomItem(tempArray); levelData[newPt.x][newPt.y]=10;//10 is mine updateNeighbors(newPt.x,newPt.y);   function updateNeighbors(i,j)//update neighbors around this mine var tileType=0; var tempArray=getNeighbors(i,j); var tmpPt; for (var k = 0; k < tempArray.length; k++)  tmpPt=tempArray[k]; tileType=levelData[tmpPt.x][tmpPt.y]; levelData[tmpPt.x][tmpPt.y]=tileType+1;  

Pour chaque mine ajoutée dans addMines, nous incrémentons la valeur du tableau stocké dans tous ses voisins. le obtenir les voisins la méthode ne retournera pas une tuile qui est en dehors de notre zone effective ou si elle contient une mine.

Appuyez sur la logique

Lorsque le joueur tape sur une tuile, nous devons trouver l’élément de tableau correspondant à l’aide du bouton findHexTile méthode expliquée plus tôt. Si l'indice de mosaïque se trouve dans notre zone effective, nous comparons simplement la valeur de l'index de tableau pour déterminer s'il s'agit d'une mosaïque vierge ou vierge..

fonction onTap () var tile = findHexTile (); if (! checkforBoundary (tile.x, tile.y)) if (checkForOccuppancy (tile.x, tile.y)) if (levelData [tile.x] [tile.y] == 10) // console .log ('boom'); var hexTile = hexGrid.getByName ("tile" + tile.x + "_" + tile.y); si (! hexTile.revealed) hexTile.reveal (); // game over else var hexTile = hexGrid.getByName ("tile" + tile.x + "_" + tile.y); if (! hexTile.revealed) if (levelData [tile.x] [tile.y] === 0) //console.log( 'révélation récursive'); recursiveReveal (tile.x, tile.y);  else //console.log('reveal '); hexTile.reveal (); révéléeTiles ++;  infoTxt.text = 'trouvé' + révélerTiles + 'sur' + blankTiles; 

Nous gardons une trace du nombre total de carreaux vierges en utilisant la variable blankTiles et le nombre de carreaux révélés à l'aide de Tuiles révélées. Une fois égaux, nous avons gagné le jeu. 

Lorsque nous tapons sur une tuile avec une valeur de tableau de 0, nous devons révéler récursivement la région avec toutes les tuiles vierges connectées. Ceci est fait par la fonction Révéler récursif, qui reçoit les indices de tuile de la tuile taraudée.

fonction recursiveReveal (i, j) var newPt = new Phaser.Point (i, j); var hexTile; var tempArray = [newPt]; voisins var; while (tempArray.length) newPt = tempArray [0]; var neighbours = getNeothers (newPt.x, newPt.y); while (voisins.length) newPt = voisins.shift (); hexTile = hexGrid.getByName ("mosaïque" + newPt.x + "_" + newPt.y); si (! hexTile.revealed) hexTile.reveal (); révéléeTiles ++; if (levelData [newPt.x] [newPt.y] === 0) tempArray.push (newPt);  newPt = tempArray.shift (); // il semblait qu'un point sans voisin échappe parfois à l'itération sans être révélé, saisissez-le ici hexTile = hexGrid.getByName ("tile" + newPt.x + "_" + newPt.y ) si (! hexTile.revealed) hexTile.reveal (); révéléeTiles ++; 

Dans cette fonction, nous trouvons les voisins de chaque tuile et révélons la valeur de cette tuile tout en ajoutant des tuiles voisines à un tableau. Nous continuons à répéter cela avec l'élément suivant du tableau jusqu'à ce que le tableau soit vide. La récursivité s’arrête lorsque nous rencontrons des éléments de tableau contenant une mine, ce qui est assuré par le fait que obtenir les voisins ne reviendra pas une tuile avec une mine.

Tuiles de marquage et de révélation

Vous devez avoir remarqué que j'utilise hexTile.reveal (), qui est rendu possible en créant un HexTile prototype qui conserve la plupart des attributs liés à notre tuile hexagonale. Je utilise l révéler fonction pour afficher le texte de la valeur de la mosaïque et définir sa couleur. De même, le toggleMark la fonction est utilisée pour marquer la tuile comme une mine quand on appuie et maintenez. HexTile a aussi un révélé attribut qui trace s'il est exploité et révélé ou non.

HexTile.prototype.reveal = function () this.tileTag.visible = true; this.revealed = true; if (this.type == 10) this.tint = '0xcc0000';  else this.tint = '0x00cc00';  HexTile.prototype.toggleMark = function () if (this.marked) this.marked = false; this.tint = '0xffffff';  else this.marked = true; this.tint = '0x0000cc'; 

Découvrez le dragueur de mines hexagonal à orientation horizontale ci-dessous. Appuyez sur pour afficher les carreaux et maintenez-le enfoncé pour marquer les mines. Il n'y a pas de jeu fini à partir de maintenant, mais si vous révélez une valeur de dix, alors c'est hasta la vista baby!

Changements pour la version verticale

Comme j'utilise la même image de pavé hexagonal pour les deux orientations, je fais pivoter le Sprite pour l'alignement vertical. Le code ci-dessous dans le HexTile prototype fait cela.

if (isVertical) this.rotation = Math.PI / 2; 

La logique du dragueur de mines reste la même pour la grille hexagonale alignée verticalement avec la différence pour findHextile et obtenir les voisins logique qui doit maintenant prendre en compte la différence d’alignement. Comme mentionné précédemment, nous devons également utiliser la transposition du tableau de niveaux avec la boucle de présentation correspondante.

Découvrez la version verticale ci-dessous.

Le reste du code dans le code source est simple et direct. Je voudrais que vous essayiez d'ajouter les fonctionnalités manquantes de redémarrage, de victoire et de fin de partie.

Conclusion

Cette approche d'un jeu hexagonal basé sur des tuiles utilisant un tableau à deux dimensions est plutôt celle d'un profane. Des approches plus intéressantes et fonctionnelles impliquent de modifier le système de coordonnées en différents types à l'aide d'équations. 

Les plus importants sont les coordonnées axiales et les coordonnées cubiques. Une série de tutoriels de suivi traitera de ces approches. En attendant, je vous recommande de lire l'article incroyablement détaillé d'Amit sur les grilles hexagonales.