JeuWeb - Crée ton jeu par navigateur
Module de carte héxagonale 2D - 3D Iso avec relief - 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 : Module de carte héxagonale 2D - 3D Iso avec relief (/showthread.php?tid=4044)

Pages : 1 2 3 4 5 6 7


RE: Module de carte héxagonale 2D - 3D Iso avec relief - comg - 08-06-2009

Non mais le truc c'est que je fais pas ça avec l'idée "pour mon jeu" mais plutot dans l'optique de faire une classe super modulable qui permettent à qui a besoin d'afficher une carte, de se faciliter la vie !
Une espèce d'une premiere pierre vers un framework Smile
Et l'hexagonale ne pose pas le problème des distance par rapport au diagonales !


RE: Module de carte héxagonale 2D - 3D Iso avec relief - Argorate - 08-06-2009

Je te souhaite bonne chance alors!

Mais il n'y a aucun problème de distance pour les diagonales (sauf si on veux s'embeté la vie encore une fois pour rien) Wink


RE: Module de carte héxagonale 2D - 3D Iso avec relief - comg - 08-06-2009

Mais les calculs sont pas excessivement compliqué avec de l'hexagonal, il suffit d'avoir les bonnes formules, s'tout. :p


RE: Module de carte héxagonale 2D - 3D Iso avec relief - Roworll - 09-06-2009

Citation :Juste une question: tu peux me donner les raisons qui te poussent à prendre des cases hexagonales (qui selon moi est non seulement beaucoup plus chiant à coder, mais qui en plus n'apporte rien, c'est même pire, ça enlève des possibilités: 6 cases, 6 directions au lieu de 8 en temps normal...)?

La structure hexagonale est pour moi héritée des wargames.
Elle présente un avantage considérable au niveau de l'équité dans les déplacements.

Dans une structure quadrillée, un déplacement en ligne/colonne et un déplacement en diagonal ne représentent pas la même distance (1 unité dans un cas, 1.41 dans l'autre).
[Image: sqcost.jpg]
Même problème pour les obstacles. Imaginons des unités (ou une barrière) placée le long d'une diagonale. Il va falloir un algorithme précis pour empêcher le passage perpendiculairement à cette diagonale
[Image: sqmove.jpg]

Bref, si l'hexagone est plus difficile à mettre en place, il offre plus de possibilités tactiques réelles.


RE: Module de carte héxagonale 2D - 3D Iso avec relief - comg - 09-06-2009

Voilà, c'est ce que je voulais dire avec les "diagonales".
Cependant, le module que je fais sera capable d'interpreter une même carte (liste de x,y) de plusieurs manières (pour l'instant hexa2D, ensuite hexa2Diso, puis ensuite je rajouterai carré ect...)
Avancement : Zoom réglé (les textures ne sont plus des background mais des images...) Cependant je suis en train d'empiler des div pour chaque cases... Est-ce vraiment bon ?
Vous pouvez donc à présent rajouter un argument "zoom" sur la barre d'adresse (avec zoom=50 la tuile de base)
[cache]
Code PHP :
<?php 
class carte
{
//----- Variables

// Infos carte
var $nom;
var
$tailleX;
var
$tailleY;

// Contenu carte
var $cases;

//----- Constantes


//----- Methodes
function __construct() {}

// Charge une carte deja enregistree
function loadCarte($id)
{
$donnees = ''; // On recupere les donnees

$this->nom = $donnees['nom'];
$this->tailleX = $donnees['tailleX'];
$this->tailleY = $donnees['tailleY'];
$this->cases = $donnees['cases'];

}

// Creer une carte vierge
function nouvelleCarte()
{
$this->nom = 'Nouvelle carte';
$this->tailleX = 1;
$this->tailleY = 1;
$this->cases = '';
}

// Enregistre la carte dans la BDD
function saveCarte($id)
{}

// Genere un hexagone parfait via GD
private function _Hexagone($n)
{
$points = array( $n/2 , 0,
3*$n/2 , 0,
2*$n , $n*0.86,
3*$n/2 , 2*$n*0.86-1,
$n/2 , 2*$n*0.86-1,
0 , $n*0.86);

header ("Content-type: image/png");
$tailleX = 2*$n;
$tailleY = 0.86*2*$n;
$image = imagecreate($tailleX,$tailleY);
$couleur = imagecolorallocate($image, 255, 255, 255);
imagecolortransparent($image, $couleur);
$noir = imagecolorallocate($image, 0, 0, 0);
ImagePolygon ($image, $points, 6, $noir);

return
imagepng($image);
}

// Affiche la carte
function afficherCarte($x_centre,$y_centre,$x_taille=0,$y_taille=0,$n=50)
{
// Taille d'affichage par défaut
if($x_taille == 0) $x_taille=$this->tailleX;
if(
$y_taille == 0) $y_taille=$this->tailleY;

// Définition des x;y de début et fin d'affichage
$x_debut = $x_centre - floor($x_taille/2);
$y_debut = $y_centre - floor($y_taille/2);
$x_fin = $x_centre + floor(($x_taille+1)/2);
$y_fin = $y_centre + floor(($y_taille+1)/2);

// Vérification des débordements et recentrage
if($x_debut < 0) // Si on déborde sur la gauche
{
$x_fin -= $x_debut;
$x_debut = 0;
}
if(
$x_fin >= $this->tailleX) // Si on déborde sur la droite
{
$x_debut -= ($x_fin - $this->tailleX);
$x_fin = $this->tailleX;
}
if(
$y_debut < 0) // Si on déborde sur le haut
{
$y_fin -= $y_debut;
$y_debut = 0;
}
if(
$y_fin >= $this->tailleY) // Si on déborde sur le bas
{
$y_debut -= ($y_fin - $this->tailleY);
$y_fin = $this->tailleY;
}

// Génération du code HTML
$aff = '<div style="position: absolute;">';
for(
$y=$y_debut;$y<$y_fin;$y++) // Chaque ligne
{
for(
$x=$x_debut;$x<$x_fin;$x++) // Chaque colonne
{
$aff .= $this->creerCase($x,$y,$n,$x_debut,$y_debut);
}
}
$aff .= '</div>';
return
$aff;
}

// Creer la case (x,y) avec un hexa de coté n et en prenant en compte le decalage
private function creerCase($x,$y,$n,$x_decalage=0,$y_decalage=0)
{
// Calcul de la position de la case
$posX = ($x-$x_decalage)*1.5*$n;
$posY = ($y-$y_decalage)*0.86*2*$n + ($x%2)*0.86*$n -1*($y-$y_decalage);
// Calcul des dimensions de la case
$l = 2*$n;
$h = 0.86*2*$n;

// Récupération des informations utiles
$adj = $this->_getAdjacentes($x,$y);
$hexa = $this->_getHexa($x,$y);
$texture = $this->_getTexture($x,$y);

// Sous couche (Texture)
$aff = '<div style="width:'. $l .'px; height:' . $h . 'px;'; // < Taille de la case
$aff .= 'position:absolute; top:'.$posY.'px;left:'.$posX.'px;'; // Position de la case
$aff .= ''; // Autre style
$aff .= 'background-color: none; ">'; // Fond de la case >

$aff .= '<img src="textures/'.$texture.'.png" alt="texture" width="'. $l .'" height="' . $h . '"/>'; // Contenu
$aff .= '</div>'; // <>

// Infos
$aff .= '<div style="width:'. $l .'px; height:' . $h . 'px;'; // < Taille de la case
$aff .= 'position:absolute; top:'.$posY.'px;left:'.$posX.'px;'; // Position de la case
$aff .= 'text-align: center;'; // Autre style
$aff .= 'background-color: none;">'; // Fond de la case >
$aff .= '(' . $x . ':' . $y . ')'; // Contenu
$aff .= '</div>'; // <>

// Sur couche (Hexa)
$aff .= '<map name="case_hexa_'.$x.'_'.$y.'">
<area shape="poly" coords="'
. ($n/2) .','. 0 .','. (3*$n/2) .','. 0 .','. (2*$n) .','. ($n*0.86) .','. (3*$n/2) .','. (2*$n*0.86-1) .','. ($n/2) .','. (2*$n*0.86-1) .','. 0 .','. ($n*0.86) .'" href="#'.$x.':'.$y.'">
</map>'
;
$aff .= '<div style="width:'. $l .'px; height:' . $h . 'px;'; // < Taille de la case
$aff .= 'position:absolute; top:'.$posY.'px;left:'.$posX.'px;'; // Position de la case
$aff .= ''; // Autre style
$aff .= 'background-color: none; ">'; // Fond de la case >
if(!is_file('hexas/'.$hexa.'.png')) $hexa = 'hexa-0';
$aff .= '<img usemap="#case_hexa_'.$x.'_'.$y.'" src="hexas/'.$hexa.'.png" alt="hexa" width="'. $l .'" height="' . $h . '"/>'; // Contenu
$aff .= '</div>'; // <>

return $aff;


}

// Récupère les infos des cases adjacentes à la case (x,y) et retourne les infos completes
private function _getAdjacentes($x,$y)
{
$p = $x%2; // Parité de X
// Coordonnées des cases adjacentes
$adj = array( 'n' => array( 'x' => $x , 'y' => $y-1 ),
'ne' => array( 'x' => $x+1 , 'y' => $y-1+$p ),
'se' => array( 'x' => $x+1 , 'y' => $y+$p ),
's' => array( 'x' => $x , 'y' => $y+1 ),
'so' => array( 'x' => $x-1 , 'y' => $y+$p ),
'no' => array( 'x' => $x-1 , 'y' => $y-1+$p ));
// Infos des cases adjacentes
$adj2 = array();
foreach(
$adj as $k => $v) // Pour chaque case adjacente
{
if(isset(
$this->cases[$v['x']][$v['y']]))
$adj2[$k] = $this->cases[$v['x']][$v['y']];
else
// Si la case n'existe pas on la considère de niveau 0 par défaut (bords de carte)
$adj2[$k] = array('altitude' => 0, 'type' => 'defaut', 'texture' => 'defaut');
}
return
$adj2;
}

// Retourne le nombre de cases adjacentes à (x,y) d'altitude z
private function _nbrAdjAlt($x,$y,$z)
{
$adj = $this->_getAdjacentes($x,$y);
$nbr = 0;
foreach(
$adj as $k => $v)
{
if(
$v['altitude']==$z)
$nbr += 1;
}
return
$nbr;
}

// Retourne l'hexa (structure) a afficher
private function _getHexa($x,$y)
{
$type = $this->cases[$x][$y]['type'];
$alt = $this->cases[$x][$y]['altitude'];
if(
$alt == 1)
{
return
'hexa-5';
}
if(
$type == 'defaut')
{
$nbradj = $this->_nbrAdjAlt($x,$y,1);
$adj = $this->_getAdjacentes($x,$y);
$return = 'hexa-'.$nbradj;
foreach(
$adj as $k => $v)
{
if(
$v['altitude']==1) $return .= '-'.$k;
}
return
$return;
}

}

// Retourne la texture a afficher
private function _getTexture($x,$y)
{
$texture = $this->cases[$x][$y]['texture'];
if(
$texture == 'herbe') return 'herbe';
elseif(
$texture == 'eau') return 'eau';
elseif(
$texture == 'defaut')
{
return
'herbe';
}
}

}
[/cache]
Je suis sûr qu'il y a moyen de se passer de la methode _nbrAdjAlt mais je ne sais pas comment le faire efficacement :/


RE: Module de carte héxagonale 2D - 3D Iso avec relief - comg - 09-06-2009

Et hop premier passage à l'hexagonal :
http://kgoyon.free.fr/map/?mode=2Diso

2 modes : 2D ou 2Diso à rentree sur la barre d'adresse

A faire :
-Regler problème de décalage dû aux cases allant sur la gauche en isometrique
- Adapter les textures dans un premier temps
- Agrandire les images pour y faire rentrer des hexas et textures en volume
NB : Le problème de décalage est visible si vous changez le nombre de case afficher = la taille de la carte avec sur la barre d'adresse tailley=5 par exemple
Décalage réglé ! Smile


RE: Module de carte héxagonale 2D - 3D Iso avec relief - comg - 09-06-2009

Ajout de lien sur les cases, afin de visualiser en carte restreinte. (Bon cliquez vous verrez x))


RE: Module de carte héxagonale 2D - 3D Iso avec relief - comg - 10-06-2009

A votre avis : Les parametres d'affichages (la case sur laquelle la carte est centree, la taille de la carte affichee, le zoom... ect) doivent il rester des parametres d'entree de la methode afficher_carte() ou serait il preferable qu'il soit des variables de la class carte ? (en sachant qu'une carte n'est pas toujours censée être affichée)

Par ce que je comment à faire passer quasiment tous ces paramètres dans des méthode prive appelées par la methode afficher_carte car ils me servent pour les calculs...

Ex : La methode afficher_carte va appelé pleins de fois la methode creer_case, or cette methode a besoin de quasiment tout les parametre d'affichage pour correctement fonctionner...

Merci d'avance.
Edit : En fait ma problematique est encore plus vaste puisque je suis en train de travailler sur les cases adjacentes à celle du joueur (afin de les munir d'un lien de deplacement)
Le problème étant que, puisque je parcours ma carte de y en y, de x en x, je vais rencontrer mon joueur après avoir etudier quelques unes des cases adjacentes à la sienne...
Séparation de la génération du html et les informations d'affichage de chaque case ? ><
Une case, pour s'afficher, à besoin de :
- ses coordonnees dans la carte complete (x, y)
- le decalage par rapport à la carte complete de la carte partielle (x_decalage, y_decalage) (communs à toutes les cases)
- ses coordonnees dans la carte partielle (affichée) (xc, yc) (dépendent de x, y, x_decalage, y_decalage)
- zoom (taille d'un coté de l'hexagone > "n") (communs à toutes les cases)
- largeur ( l ), hauteur ( h ) (dépendent de n)
- sa position (posX, posY) (dépendent de x (si crenelage en x), y (si crenelage en y), xc, yc, n)
- du mode d'affichage (mode = 2D, 2Diso) (communs à toutes les cases)
- la taille de la carte partielle (taillex (si crenelage en x), tailley (si crenelage en y)) (communs à toutes les cases)

Donc si je veux faire une étape intermediaire, c'est à dire que la methode afficher va d'abord stocké toutes ces infos dans un tableau, puis ce tableau sera ensuite interpréter en HTML (ce qui laisse la possibilité de l'interpreter dans d'autre langage Wink). Entre ces 2 étapes je pourrai alors modifier des cases déjà évaluées.

Qu'en pensez vous ?

ComG, en mode monologue x)
Donc au final, les seules infos particulières à UNE case, et qui ne peuvent pas se déduire des infos GLOBALES sont :
- xc (on peut en deduire x par x_decalage)
- yc (on peut en déduire y par y_decalage)
Ensuite les informations finalement affichées :
- hexa (structure) (n'a aucune raison d'être modifié par une case évalué après)
- texture (n'a aucune raison d'être modifié par une case evalué après)
- objet/batiment/decor (n'a aucune raison d'être modifié par une case evalué après)
- personnage (n'a aucune raison d'être modifié par une case evalué après)
- informations sur la case (n'a aucune raison d'être modifié par une case evalué après)
- liens (deplacement pour une case adjacente, interaction pour une case où se trouve un autre joueur, juste acces aux infos pour une case dans le champs de vision, aucune infos pour les cases hors champ de vision...) <<< On peut donc jouer juste sur une valeur qui classe la case selon cela

soit =>
Code :
xc | yc | type
Avec type =
- adjacente
- adjacente + autre joueur
- dans le champs de vision
- dans le champs de vision + autre joueur
- hors champ de vision

On pourrait alors diviser ce "type" en 2 champs
Code :
xc | yc | distance | joueur
Ou distance serait le nombre de case entre la case courant et la case du joueur actif et joueur prendrait l'ID d'un autre joueur
Bien entendu, tout cela par rapport à une seule case qui est la case du joueur actif !
Il faudra cependant gerer le cas ou la carte prend en compte ce joueur actif (champs de vision), ou bien s'il ne s'agit que d'une navigation sur la carte...


RE: Module de carte héxagonale 2D - 3D Iso avec relief - comg - 10-06-2009

Voilà, j'ai presque finit de restructurer ma classe de manière à séparer au maximum l'affichage de la carte de la récupération d'infos de la carte, ce qui permettra, sans altérer la carte, d'en modifier les cases affichées (par exemple pour une zone de perception)
Quelqu'un connait les formules de distance sur une hexmap ? Smile
Je suis un peu perdu dans ma recherche.

Si je trouve je la posterai ici !

ComG, va devenir fort en hexmap x)
NB : Je parle d'une distance plutôt en "nombre de case entre (xa,ya) et (xb,yb)".


RE: Module de carte héxagonale 2D - 3D Iso avec relief - comg - 10-06-2009

Je cherche actuellement les conditions sur x et y pour que ces cases soit à une distance d de la case xa, xb
Avec p = x%2 (parité de x : p=1 si x impair, p=0 si x pair)

if( x <= xa + d AND x >= xa - d AND y <= ya + d AND y >= ya - d )