J'essaye de faire un pixel à la fonction coord pour une carte hexadécimale mais je ne reçois pas les calculs correctement, tout ce que j'essaie semble être un peu décalé, et les exemples que j'ai trouvés étaient basés sur des cartes centrées encerclées.
Par «basé sur un tableau», je veux dire la façon dont les hexs sont ordonnés, voir photo.
Le résultat le plus précis que j'ai obtenu était avec le code suivant, mais il est toujours désactivé et s'aggrave plus les valeurs augmentent:
public HexCell<T> coordsToHexCell(float x, float y){
final float size = this.size; // cell size
float q = (float) ((1f/3f* Math.sqrt(3) * x - 1f/3f * y) / size);
float r = 2f/3f * y / size;
return getHexCell((int) r, (int) q);
}
L'écran commence par 0,0 en haut à gauche, chaque cellule connaît son centre.
Tout ce dont j'ai besoin, c'est d'un moyen de traduire les coordonnées de l'écran en coordonnées hexadécimales. Comment pourrais-je faire ça?
la source
Il y a deux façons de gérer ce problème, à mon avis.
Utilisez un meilleur système de coordonnées. Vous pouvez vous faciliter la tâche si vous savez comment numéroter les hexs. Amit Patel a la référence définitive sur les grilles hexagonales. Vous voudrez rechercher des coordonnées axiales sur cette page.
Emprunter du code à quelqu'un qui l'a déjà résolu. J'ai un code qui fonctionne, que j'ai retiré de la source de Battle for Wesnoth . Gardez à l'esprit que ma version a la partie plate des hexagones sur le dessus, vous devrez donc échanger x et y.
la source
Je pense que la réponse de Michael Kristofik est correcte, en particulier pour mentionner le site Web d'Amit Patel, mais je voulais partager mon approche novice des grilles hexadécimales.
Ce code a été tiré d'un projet auquel j'ai perdu tout intérêt et abandonné écrit en JavaScript, mais la position de la souris sur la tuile hexadécimale a très bien fonctionné. J'ai utilisé * cet article GameDev * pour mes références. De ce site Web, l'auteur avait cette image qui montrait comment représenter mathématiquement tous les côtés et positions hexagonaux.
Dans ma classe de rendu, j'ai défini ceci dans une méthode qui m'a permis de définir la longueur de côté hexadécimale que je voulais. Affiché ici parce que certaines de ces valeurs ont été référencées dans le code de coordonnées pixel à hex.
Dans la classe d'entrée de souris, j'ai créé une méthode qui a accepté une coordonnée d'écran x et y et a renvoyé un objet avec la coordonnée hexadécimale dans laquelle se trouve le pixel. * Notez que j'avais une fausse "caméra", donc les décalages pour la position de rendu sont également inclus.
Enfin, voici une capture d'écran de mon projet avec le débogage du rendu activé. Il montre les lignes rouges où le code vérifie les cellules TypeA vs TypeB ainsi que les coordonnées hexadécimales et les cellules décrivent
J'espère que cela aide certains.
la source
J'ai en fait trouvé une solution sans calcul hexadécimal.
Comme je l'ai mentionné dans la question, chaque cellule enregistre ses propres coordonnées centrales, en calculant le centre hexadécimal le plus proche des coordonnées pixel, je peux déterminer la cellule hexadécimale correspondante avec une précision en pixels (ou très proche).
Je ne pense pas que ce soit la meilleure façon de le faire, car je dois itérer sur chaque cellule et je peux voir comment cela pourrait être taxable, mais je laisserai le code comme solution alternative:
la source
0…cols-1
et toutes les lignes0…rows-1
, vous pouvez analysercol_guess - 1 … col_guess+1
etrow_guess - 1 … row_guess + 1
. Cela ne fait que 9 hexagones donc c'est rapide et ne dépend pas de la taille de la carte.Voici les tripes d'une implémentation C # d'une des techniques publiées sur le site Web d'Amit Patel (je suis sûr que la traduction en Java ne sera pas un défi):
Le reste du projet est disponible ici en Open Source, y compris les classes MatrixInt2D et VectorInt2D référencées ci-dessus:
http://hexgridutilities.codeplex.com/
Bien que l'implémentation ci-dessus concerne les hexs à sommet plat, la bibliothèque HexgridUtilities inclut l'option de transposition de la grille.
la source
J'ai trouvé une approche simple et alternative qui utilise la même logique qu'un damier ordinaire. Il crée un effet d'accrochage à la grille avec des points au centre de chaque tuile et à chaque sommet (en créant une grille plus serrée et en ignorant les points alternés).
Cette approche fonctionne bien pour des jeux comme Catan, où les joueurs interagissent avec les tuiles et les sommets, mais n'est pas adaptée aux jeux où les joueurs n'interagissent qu'avec les tuiles, car elle renvoie le point central ou le sommet dont les coordonnées sont les plus proches, plutôt que la tuile hexagonale les coordonnées sont à l'intérieur.
La géométrie
Si vous placez des points dans une grille avec des colonnes qui font le quart de la largeur d'une tuile et des lignes qui font la moitié de la hauteur d'une tuile, vous obtenez ce modèle:
Si vous modifiez ensuite le code pour ignorer chaque deuxième point dans un motif en damier (sauter
if column % 2 + row % 2 == 1
), vous vous retrouvez avec ce motif:la mise en oeuvre
Avec cette géométrie à l'esprit, vous pouvez créer un tableau 2D (comme vous le feriez avec une grille carrée), en stockant les
x, y
coordonnées de chaque point de la grille (à partir du premier diagramme) - quelque chose comme ceci:Remarque: Comme d'habitude, lorsque vous créez une grille autour des points (plutôt que de placer des points sur les points eux-mêmes), vous devez décaler l'origine (en soustrayant la moitié de la largeur d'une colonne
x
et la moitié de la hauteur d'une ligney
).Maintenant que votre tableau 2D (
points
) est initialisé, vous pouvez trouver le point le plus proche de la souris comme vous le feriez sur une grille carrée, n'ayant qu'à ignorer tous les autres points pour produire le motif dans le deuxième diagramme:Cela fonctionnera, mais les coordonnées sont arrondies au point le plus proche (ou aucun point) en fonction du rectangle invisible dans lequel se trouve le pointeur. Vous voulez vraiment une zone circulaire autour du point (donc la plage d'accrochage est égale dans toutes les directions). Maintenant que vous savez quel point vérifier, vous pouvez facilement trouver la distance (en utilisant le théorème de Pythagore). Le cercle implicite devrait toujours tenir à l'intérieur du rectangle de délimitation d'origine, limitant son diamètre maximal à la largeur d'une colonne (un quart de la largeur d'une tuile), mais qui est toujours assez grand pour bien fonctionner en pratique.
la source