JeuWeb - Crée ton jeu par navigateur
Coordonnées des points d'une case hexagonale en vue 3D iso. - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Coordonnées des points d'une case hexagonale en vue 3D iso. (/showthread.php?tid=5662)



Coordonnées des points d'une case hexagonale en vue 3D iso. - Maz - 24-08-2011

Bonjour, je suis confronté à un léger soucis: j'aimerais développer une carte en vue 3D Iso avec des cases hexagonales, jusque là rien de grave, je peut me baser sur le tuto d'Harparine pour les calculs principaux. Mais Harparine se base sur une image pour rédiger ce tutoriel, hors j'aurais besoin de calculer la position de chaque point d'un hexagone en vue 3D ISO mathématiquement, ceci afin de généré une carte au format vectoriel SVG.

J'ai compris les calculs pour tourner la case de 45°:
Code :
cotéTuile = 20
largeurTuile = (sin(15)+sin(75)+sin(45))*cotéTuile
hauteurTuile = largeurTuile
x1 = sin(15)*cotéTuile
y1 = sin(15)*cotéTuile
x2 = largeurTuile-sin(45)*cotéTuile
y2 = 0
x3 = largeurTuile
y3 = sin(45)*cotéTuile
x4 = largeurTuile-sin(15)*cotéTuile
y4 = hauteurTuile-sin(15)*cotéTuile
x5 = sin(45)*cotéTuile
y5 = hauteurTuile
x6 = 0
y6 = hauteurTuile-sin(45)*cotéTuile

Mais comment l'aplatir?

Edit: Eurêka, enfin je crois:
Code :
cotéTuile = 20
largeurTuile = (sin(15)+sin(75)+sin(45))*cotéTuile
hauteurTuile = largeurTuile/2
x1 = sin(15)*cotéTuile
y1 = sin(15)*cotéTuile/2
x2 = largeurTuile-sin(45)*cotéTuile
y2 = 0
x3 = largeurTuile
y3 = sin(45)*cotéTuile/2
x4 = largeurTuile-sin(15)*cotéTuile
y4 = hauteurTuile-sin(15)*cotéTuile/2
x5 = sin(45)*cotéTuile
y5 = hauteurTuile
x6 = 0
y6 = hauteurTuile-sin(45)*cotéTuile/2

L'apparence a l'air bonne (cf. pièce jointe):



RE: Coordonnées des points d'une case hexagonale en vue 3D iso. - Roworll - 25-08-2011

Pour ma part, je ne travaillerais pas hexagone par hexagone pour gèrer les rotations.
En utilisant les définitions (defs), les groupes (g) et les transform, tu peux facilement tirer partie de la puissance du SVG pour régler ton problème.

Voici par exemple, une approche possible
- Les différents hexagones sont placés dans les définitions (defs) avec un id correspondant. Ces définitions composeront ta bibliothèque de référence pour la construction de la carte
- Pour le rendu de la carte, à chaque hexagone devant être dessiné, tu pioches dans le contenu de tes définitions via xlink:href et tu appliques un transform/translate pour placer l'élément au bon endroit. L'ensemble est contenu dans un groupe (g).
- Une fois tous les hexagones correctement placés dans ton groupe, il suffit d'appliquer une dernière transformation pour effectuer la rotation et le redimensionnement (scale + rotate) et le tour est joué.

Voici un lien vers un vieil exemple
En cliquant sur les boutons pour changer le rendu (iso/défaut), il n'y a aucun réaffichage. Juste une manipulation de l'attribut "Transform".


RE: Coordonnées des points d'une case hexagonale en vue 3D iso. - Maz - 25-08-2011

Intéressante approche, qui pourrais alléger mon code et mon serveur pour les calculs... Mais donc de php à svg, qu'elle donnée passes-tu? les coordonnée x;y de chaque case seulement?


RE: Coordonnées des points d'une case hexagonale en vue 3D iso. - Roworll - 26-08-2011

Dans l'exemple que j'ai donné, mon code PHP génère un fichier XML qui est mis en forme via une feuille XSL.
Le but de tout ça est de délocaliser un maximum vers le client.

Chaque hexagone est encodé comme suit


<hex type="hwo" x="-8" y="0" z="-8" r="d0" w="a5"/>
- Type est le type de terrain
- x/y/z sont les coordonnées
- r est utilisé pour la surcouche des routes
- w est utilisé pour la surcouche des rivières

Voici la définition d'un hexagone de type hwo

<g id="hwo">
<use xlink:href="#hex" fill="#96c864" />
<use xlink:href="#tree" fill="#96c864" transform="translate(10 3)"/>
<use xlink:href="#tree" fill="#96c864" transform="translate(5 5)"/>
<use xlink:href="#tree" fill="#96c864" transform="translate(15 5)"/>
<use xlink:href="#tree" fill="#96c864" transform="translate(10 9)"/>
</g>
Comme on peut le voir, cet hexagone se compose d'une forme de base (#hex) et de quatres éléments #tree placés à divers endroits.

Tout ceci est inclus dans la section defs pour être réutilisé facilement.

A l'affichage, mon XSL calcule les coordonnées grâce aux attributs @x/@y/@z ce qui me permet de définir les coordonnées cartésiennes attendues ($posx/$posy)

Le code pour le rendu de la case est le suivant

<!-- Création d'un groupe correctement positionné grâce au transform en utilisant les coordonnées calculées -->
<g id="h_{@x}_{@y}_{@z}" transform="translate({$posx + 180} {$posy + 210})">
<xsl:if test="(($dx) > $view or ($dy) > $view or ($dz) > $view) ">
<!-- Hexagone hord du champ de vision - passage au gris-->
<xsl:attribute name="filter">url(#GrayScale)</xsl:attribute>
</xsl:if>
<!-- Affichage du modèle de base -->
<use xlink:href="#{@type}"/>
<xsl:if test="@w != ''">
<!-- Il y a une rivière à afficher -->
<use xlink:href="#water_{substring(@w,1,1)}" transform="rotate({substring(@w,2,1) * 60} 15 12.8)" />
</xsl:if>
<xsl:if test="@r != ''">
<!-- Il y a une route à afficher -->
<use xlink:href="#road_{substring(@r,1,1)}" transform="rotate({substring(@r,2,1) * 60} 15 13)" />
</xsl:if>
</g>

J'ai mis à jour mon lien original pour y inclure une petite fonctionnalité additionnelle. permettant de simuler un rayon de vision.

Si l'hexagone est hors du rayon de perception, il est affiché dans une nuance de gris via l'ajout de l'attribut filter="url(#GrayScale)"

Pour obtenir l'effet, j'ai juste fait appel à un filtre, lui aussi créé dans la section defs


<filter id="GrayScale" filterUnits="userSpaceOnUse" x="0" y="0" width="40" height="40">
<feColorMatrix in="SourceGraphic" type="matrix"
values="0.3333 0.3333 0.3333 0 0
0.3333 0.3333 0.3333 0 0
0.3333 0.3333 0.3333 0 0
0 0 0 1 0"/>
</filter>
Si tu veux regarder plus en profondeur, tu peux jeter un œil au source de la page pour voir le xml et cliquer sur ce lien pour regarder le xsl.

Attention, c'est du vieux code qui me servait uniquement à faire quelques tests. Pas toujours cohérent ni propre donc.