A la recherche des bonnes formules pour positionner des hexagones
#1
Hello,

Je cherche à représenter une grille d'hexagones qui suit ce repère :

[Image: repere.png]

Je place le point d'origine (le "milieu") de mon hexagone 0, 0 au milieu de la carte. Je veux ensuite positionner les autres autour dans le respect de mon repère.

Comme je suis en CSS, je dois raisonner en "top" et en "left" (je garde les termes de x et y pour parler des coordonnées de mon repère) depuis le coin supérieur gauche de mon bloc qui contient la carte : mais les hexagones pourront en sortir (avec des top et left négatifs ou importants).

J'ai bricolé quelques formules qui me font un joli pavage mais qui ne correspondent pas du tout à mon modèle. C'est visible ici : http://maitreromain.alwaysdata.net/diggers/.

[Image: screenshot.png]

Le problème, c'est que ça ne colle pas avec mon repère de référence. J'ai donc besoin d'aide pour trouver des formules qui produisent le positionnement que j'expose dans mon repère. Si quelqu'un est prêt à m'aider à les trouver, voici une archive de la page montrée ici, pour pouvoir la manipuler facilement. Le calcul se trouve dans la fonction "add" du fichier app.js.

Merci d'avance ! <3
Répondre
#2
FRANCHEMENT, t'aurais pas pu poster ça plus tôt, hein ?

Bref, je passe pour le moment, mais en tout cas le style est vraiment classe.
Répondre
#3
Salut,

un hexagone est constitué de triangles équilatéraux, dont la longueur (L) est celle du côté de l'hexagone. La longueur du pavage (de la répétition des hexagones) sur l'axe horizontal est donc de 3L (1x en diagonale de l'hexagone 0,0 + 1x le côté de l'hexagone 0,-1 + 1x en diagonale de l'hexagone 1,-1). La longueur du pavage sur l'axe vertical est donc de 2xH, H étant la hauteur du triangle équilatéral (donc, L² = H² + (L/2)² => H = sqrt(L² - L²/4) = L*sqrt(3)/2) => donc la longueur verticale est de L * sqrt(3)

Sinon, pour respecter les axes que tu demandes (je les trouve vraiment pas pratiques perso?! pourquoi ne pas garder les axes verticaux et horizontaux de l'écran, qui seront alors simplement orthogonaux mais non-normés?), il faut (X/Y sont des vecteurs exprimés en [horizontal ; vertical] donc en [left;top]):
X = [L + L/2, H] = [1.5*L, sqrt(3)/2*L]
Y = [-L - L/2, H] = [-1.5*L, sqrt(3)/2*L]

L'hexa [-1, -3] en bas à gauche de l'image devrait donc être en left=1.5*L*-1 + -1.5*L*-3 = 3*L et top=-(sqrt(3)/2*L*-1 + sqrt(3)/2*L*-3) = 2*sqrt(3)*L
Le "-" de top vient de l'axe vertical dirigé "vers le bas" sur l'écran (alors que tu l'as dirigé vers le haut sur le schéma)

A partir de là, tu devrais pouvoir faire ton pavage en CSS 2
Répondre
#4
J'adore le style graphique.

J'avais répondu sur discord mais t'as du partir dormir avant :
[Image: Sans_titre.png]
A et B sont à mesurer en pixel.
left = B * (X-Y)
top = A / 2 * (X+Y)


L'autre problème que je vois sur ton screenshoot c'est que la case 0,1 est dessinée par dessus la case 0,0. Donc besoin de rajouter une rêgle css pour que les cases soient dessinées par "top" croissant.
Répondre
#5
Coucou ! Merci pour votre aide ! J'ai implémenté ça et j'ai le résultat que je voulais.

[Image: rendu-final.png]


J'ai défini l'origine de ma carte :

Code :
const originX = map.offsetWidth/2 - tileOriginX * scale;
const originY = map.offsetHeight/2 - tileOriginY * scale;

J'ai calculé les distances A et B du diagramme de mon sauveur Thêta Tau Tau :

Code :
const distanceBetweenOriginsX = hexagonWidth * 2/3;
const distanceBetweenOriginsY = hexagonHeight;

J'ai appliqué la formulé proposée pour chaque tuile afin de déterminer son décalage :

Code :
tile.style.left = Math.round(originX + (distanceBetweenOriginsX * (x - y) * scale));
tile.style.top = Math.round(originY - (distanceBetweenOriginsY / 2 * (x + y) * scale));

J'ai ensuite dû gérer le zIndex pour afficher correctement les chevauchements. Je suis parti du principe que plus un Y était bas (vers la droite), plus son affichage était prioritaire, puis on ordonnait ensuite par X le plus bas. J'ai besoin de valeurs positives donc je transforme ma valeur de Y et X.

Code :
function assignZIndex(tiles) {
  tiles.elements.map(function(tile) {
    const scoreY = Math.round(mapValue(parseInt(tile.dataset.y), tiles.maxY, tiles.minY, 1, 100));
    const scoreX = Math.round(mapValue(parseInt(tile.dataset.x), tiles.minX, tiles.maxX, 1, 100));
    tile.style.zIndex = scoreY * 100 - scoreX;
  });
}

Merci à tous ! 2


Pour info, ces jolis graphismes créés par Steven Colling ne coûtent qu'une dizaine d'euros !
Répondre
#6
Hello question et remarque

Je suis pas sur qu’il y est besoin du z index : si tu boucles du haut vers le bas de gauche vers la droite, l hexagone prioritaire sera celui en dessous, à droite

Après ma question concerne la montagne ( ou tout élément de décor qui dépasse la case) comment tu le gères ? Chaque image a un spacer transparent tout autour d’elle (et qui se remplit d une montagne si besoin) ?

En fait j’imaginais au départ un positionnement css bottom right pour permettre des images plus ou moins grandes de se positionner mais on aurait le même problème pour afficher des trucs qui débordent vers le bas
[WIP]projet Rivages
[WIP]projet Arthur (comme si ça suffisait pas d'un...)
Répondre
#7
Je dirais qu'il faut choisir. À mon avis le set d'image ne déborde jamais vers le bas.
Répondre
#8
Et si ça déborde vers le bas (et qu'on veut que ça déborde vers le base parce qu'on veut complexifier 2 ) alors il faut passer par plusieurs layers (chacun ayant la règle que Sephi a fixé: les tuiles du bas sont dessinées par-dessus celles du haut).
C'est ce que j'ai sur ECLERD: un layer de fond, puis un layer de sprites (par-dessus le layer de fond) qui contient les montagnes ou les batiments
Répondre
#9
Mais dans ce cas il te faut d'autres layers. par exemple ton plamier géant va déborder vers le bas et doit passer au dessus des buissons de la tuile inférieure ! Mais les buissons passent au dessus du tronc du palmier …
Répondre
#10
Je ne vois pas pourquoi le palmier débordant vers le bas serait rendu par-dessus les buissons? Le palmier et les buissons font parti du même layer (celui des sprites on va dire) donc les buissons (plus bas & dans le même layer) sont rendus par-dessus le palmier (plus haut et dans le même layer). S'ils sont dans des layers différents, oui, y'a soucis mais je vois pas pourquoi ils le seraient.

Dis autrement, j'ai un layer pour le rendu des éléments "horizontaux" (le fond des tuiles) et un layer pour les éléments verticaux (un palmier). L'implication, c'est qu'on a des sprites qui n'ont pas d'épaisseur sur Y
Répondre


Sujets apparemment similaires...
Sujet Auteur Réponses Affichages Dernier message
  [RESOLU]Comment positionner sur une grande map Air 3 921 06-13-2017, 07:14 PM
Dernier message: Air



Utilisateur(s) parcourant ce sujet : 1 visiteur(s)