Stockage d'une grille hexadécimale

10

J'ai créé un petit cadre de grille hexadécimal pour Unity3D et suis arrivé au dilemme suivant. Voici mon système de coordonnées (extrait d' ici ):

entrez la description de l'image ici

Tout fonctionne très bien, sauf que je ne sais pas comment le stocker. J'avais initialement l'intention de stocker cela dans un tableau 2D et d'utiliser des images pour générer mes cartes.

Un problème était qu'il avait des valeurs négatives (cela a été facilement corrigé en décalant un peu les coordonnées).

Cependant, en raison de ce système de coordonnées, une telle image ou bitmap devrait être en forme de losange - et puisque ces structures sont de forme carrée, cela causerait beaucoup de maux de tête même si je pirate quelque chose ensemble. Y a-t-il quelque chose qui me manque qui pourrait résoudre ce problème? Je me souviens avoir vu un message sur ce sujet dans les forums de l'unité, mais je ne trouve plus le lien.

L'écriture d'un ensemble de traducteurs de coordonnées est-elle la meilleure solution ici?

Si vous pensez que ce serait utile, je peux poster du code et des images de mon problème.

PeeC
la source
1
Ne pouvez-vous pas simplement enregistrer des images PNG transparentes autour des hexagones?
Markus von Broady
Mon principal problème avec l'enregistrement dans les pngs et les tableaux est la quantité d '"espaces blancs" qu'ils devraient contenir afin de garder ce système de coordonnées intact.
PeeC
1
Si "espace blanc" signifie pixels transparents, alors pourquoi la quantité est-elle un problème?
Markus von Broady
C'est un très bon point. La plupart des formats d'image ne gaspillent pas beaucoup de mémoire pour stocker des motifs répétés. Mais encore, il me agace un peu que pour stocker cette carte J'utilise cette quantité de mémoire (pixels gris sont un espace vide, d' autres couleurs sont coordonnées hexagonales valides).
PeeC
1
Oh, vous stockez les données de la grille, pas les images en mosaïque! Pourquoi ne pas simplement enregistrer vos structures de données (grille) dans un fichier binaire, ou les encoder en utilisant par exemple JSON et enregistrer dans un fichier texte? Je ne connais pas les capacités d'Unity, cependant. Aussi, vous voudrez peut-être le confirmer, mais je crois qu'une zone de même couleur est optimisée (compressée de manière lâche) au format PNG.
Markus von Broady

Réponses:

9

Les coordonnées du parallélogramme que vous utilisez sont plus faciles à utiliser, mais elles ont l'inconvénient d'être étranges pour les cartes rectangulaires. Une approche consiste à le stocker avec les coordonnées de décalage mais à utiliser des coordonnées de parallélogramme dans votre logique de jeu.

Observation: dans chaque ligne de la carte, les données de la grille sont contiguës. Tout l'espace perdu est à gauche et à droite.

Solution: dans cette ligne, stockez les données en commençant par la colonne la plus à gauche au lieu de la colonne marquée 0. Calculez la première colonne de la carte rectangulaire dans votre système de coordonnées , puis soustrayez-la des coordonnées de la colonne pour déterminer où elle va dans le tableau. Cela fonctionne également pour les coordonnées de colonne négatives.

Effectuez la conversion dans le getter et le setter pour la carte, avec quelque chose comme ceci:

inline function get(q, r) {
    first_column_in_this_row = -floor(q/2);
    return array[r][q - first_column_in_this_row];
}

Vous devrez le modifier pour travailler avec votre choix de coordonnées et de carte (faites attention à une différence). Dans certaines dispositions, vous souhaiterez compenser les colonnes par la ligne au lieu de l'inverse.

Vous pouvez utiliser la même astuce pour créer des cartes d'autres formes; ce n'est pas limité aux rectangles.

Si vous utilisez C ou C ++, vous pouvez utiliser l'arithmétique des pointeurs pour accélérer les choses. Au lieu de stocker un tableau de pointeurs dans des tableaux, stockez un tableau de pointeurs qui ont été ajustés par first_column_in_row. (Cela peut ne pas être portable)

amitp
la source
Cela fonctionne pour autant que je sache, mais les mathématiques étaient vraiment étranges. Après avoir essayé plusieurs équations qui avaient du sens dans ma tête, je me suis installé yIndex = y-((x%2==0)?(x/2-x):(-x/2)-1)après quelques essais et erreurs. Je ne sais pas comment cela fonctionne dur.
PeeC
Faites ça yIndex = y-((x%2==0)?(-x/2):(-x/2)-1). x / 2 est entièrement basé sur des nombres entiers, donc pas besoin de plancher.
PeeC
6

Personnellement, je préférerais la simplicité à la sauvegarde de la mémoire. N'optimisez pas tant que vous n'en avez pas besoin!

Si vous êtes toujours déterminé à économiser quelques octets, voici comment vous pouvez le faire:

entrez la description de l'image ici

  1. Coupez le parallélogramme en deux pour former deux triangles rectangles
  2. Réorganisez les deux triangles pour former un rectangle.
  3. (Notez que j'ai ajouté la bande tampon verte pour que les calculs fonctionnent bien.)

Code Python pour mapper les coordonnées du rectangle aux coordonnées du parallélogramme et inversement:

# Height of rectangle
H = 15

def r2p(x, y):
"rectangle to parallelogram"
if y < -x/2 + H:
    y = y + H
return (x - 1, y)

def p2r(x,y):
"parallelogram to rectangle"
if y >= H:
    y = y - H
return (x + 1, y)
Leftium
la source
2
vous pouvez également déplacer les pixels verticalement vers le bas - sur l'image qui seraitoffsetY = Math.floor ( (x+1)/2 )
Markus von Broady