* Modifier: Correction d'une erreur en javascript qui provoquait une erreur sur Firefox *
Edit: vient d'ajouter la possibilité de redimensionner les hexs au code source PHP. De minuscules 1/2 ou 2x jumbo, tout dépend de vous :)
Je ne savais pas trop comment mettre tout cela par écrit, mais j'ai trouvé qu'il était plus facile d'écrire simplement le code pour un exemple en direct complet. La page (lien et source ci-dessous) génère dynamiquement une hexmap avec PHP et utilise Javascript pour gérer les clics sur la carte. Cliquer sur un hexagone le met en surbrillance.
La carte est générée de manière aléatoire, mais vous devriez pouvoir utiliser votre propre code à la place pour remplir la carte. Il est représenté par un simple tableau 2D, chaque élément du tableau contenant le type de terrain présent dans cet hex.
Cliquez-moi pour essayer l'exemple de carte hexadécimale
Pour l'utiliser, cliquez sur n'importe quel hex pour le mettre en surbrillance.
En ce moment, il génère une carte 10x10, mais vous pouvez changer la taille de la carte en PHP pour qu'elle soit de la taille que vous souhaitez. J'utilise également un ensemble de tuiles du jeu Wesnoth pour l'exemple. Ils mesurent 72 x 72 pixels, mais la source vous permet également de définir la taille de vos tuiles hexagonales.
Les hexs sont représentés par des images PNG avec des zones "hors de l'hex" définies comme transparentes. Pour positionner chaque hex, j'utilise CSS pour définir la position absolue de chaque tuile, calculée par les coordonnées de la grille hexadécimale. La carte est incluse dans un seul DIV, ce qui devrait vous permettre de modifier plus facilement l'exemple.
Voici le code de la page complète. Vous pouvez également télécharger la source de démonstration (y compris toutes les images hexadécimales).
<?php
// ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// :: HEX.PHP
// ::
// :: Author:
// :: Tim Holt, [email protected]
// :: Description:
// :: Generates a random hex map from a set of terrain types, then
// :: outputs HTML to display the map. Also outputs Javascript
// :: to handle mouse clicks on the map. When a mouse click is
// :: detected, the hex cell clicked is determined, and then the
// :: cell is highlighted.
// :: Usage Restrictions:
// :: Available for any use.
// :: Notes:
// :: Some content (where noted) copied and/or derived from other
// :: sources.
// :: Images used in this example are from the game Wesnoth.
// ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// --- Turn up error reporting in PHP
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
// --- Define some constants
$MAP_WIDTH = 10;
$MAP_HEIGHT = 10;
$HEX_HEIGHT = 72;
// --- Use this to scale the hexes smaller or larger than the actual graphics
$HEX_SCALED_HEIGHT = $HEX_HEIGHT * 1.0;
$HEX_SIDE = $HEX_SCALED_HEIGHT / 2;
?>
<html>
<head>
<title>Hex Map Demo</title>
<!-- Stylesheet to define map boundary area and hex style -->
<style type="text/css">
body {
/*
margin: 0;
padding: 0;
*/
}
.hexmap {
width: <?php echo $MAP_WIDTH * $HEX_SIDE * 1.5 + $HEX_SIDE/2; ?>px;
height: <?php echo $MAP_HEIGHT * $HEX_SCALED_HEIGHT + $HEX_SIDE; ?>px;
position: relative;
background: #000;
}
.hex-key-element {
width: <?php echo $HEX_HEIGHT * 1.5; ?>px;
height: <?php echo $HEX_HEIGHT * 1.5; ?>px;
border: 1px solid #fff;
float: left;
text-align: center;
}
.hex {
position: absolute;
width: <?php echo $HEX_SCALED_HEIGHT ?>;
height: <?php echo $HEX_SCALED_HEIGHT ?>;
}
</style>
</head>
<body>
<script>
function handle_map_click(event) {
// ----------------------------------------------------------------------
// --- This function gets a mouse click on the map, converts the click to
// --- hex map coordinates, then moves the highlight image to be over the
// --- clicked on hex.
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
// --- Determine coordinate of map div as we want the click coordinate as
// --- we want the mouse click relative to this div.
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
// --- Code based on http://www.quirksmode.org/js/events_properties.html
// ----------------------------------------------------------------------
var posx = 0;
var posy = 0;
if (event.pageX || event.pageY) {
posx = event.pageX;
posy = event.pageY;
} else if (event.clientX || e.clientY) {
posx = event.clientX + document.body.scrollLeft
+ document.documentElement.scrollLeft;
posy = event.clientY + document.body.scrollTop
+ document.documentElement.scrollTop;
}
// --- Apply offset for the map div
var map = document.getElementById('hexmap');
posx = posx - map.offsetLeft;
posy = posy - map.offsetTop;
//console.log ("posx = " + posx + ", posy = " + posy);
// ----------------------------------------------------------------------
// --- Convert mouse click to hex grid coordinate
// --- Code is from http://www-cs-students.stanford.edu/~amitp/Articles/GridToHex.html
// ----------------------------------------------------------------------
var hex_height = <?php echo $HEX_SCALED_HEIGHT; ?>;
x = (posx - (hex_height/2)) / (hex_height * 0.75);
y = (posy - (hex_height/2)) / hex_height;
z = -0.5 * x - y;
y = -0.5 * x + y;
ix = Math.floor(x+0.5);
iy = Math.floor(y+0.5);
iz = Math.floor(z+0.5);
s = ix + iy + iz;
if (s) {
abs_dx = Math.abs(ix-x);
abs_dy = Math.abs(iy-y);
abs_dz = Math.abs(iz-z);
if (abs_dx >= abs_dy && abs_dx >= abs_dz) {
ix -= s;
} else if (abs_dy >= abs_dx && abs_dy >= abs_dz) {
iy -= s;
} else {
iz -= s;
}
}
// ----------------------------------------------------------------------
// --- map_x and map_y are the map coordinates of the click
// ----------------------------------------------------------------------
map_x = ix;
map_y = (iy - iz + (1 - ix %2 ) ) / 2 - 0.5;
// ----------------------------------------------------------------------
// --- Calculate coordinates of this hex. We will use this
// --- to place the highlight image.
// ----------------------------------------------------------------------
tx = map_x * <?php echo $HEX_SIDE ?> * 1.5;
ty = map_y * <?php echo $HEX_SCALED_HEIGHT ?> + (map_x % 2) * (<?php echo $HEX_SCALED_HEIGHT ?> / 2);
// ----------------------------------------------------------------------
// --- Get the highlight image by ID
// ----------------------------------------------------------------------
var highlight = document.getElementById('highlight');
// ----------------------------------------------------------------------
// --- Set position to be over the clicked on hex
// ----------------------------------------------------------------------
highlight.style.left = tx + 'px';
highlight.style.top = ty + 'px';
}
</script>
<?php
// ----------------------------------------------------------------------
// --- This is a list of possible terrain types and the
// --- image to use to render the hex.
// ----------------------------------------------------------------------
$terrain_images = array("grass" => "grass-r1.png",
"dirt" => "dirt.png",
"water" => "coast.png",
"path" => "stone-path.png",
"swamp" => "water-tile.png",
"desert" => "desert.png",
"oasis" => "desert-oasis-tile.png",
"forest" => "forested-mixed-summer-hills-tile.png",
"hills" => "hills-variation3.png",
"mountain" => "mountain-tile.png");
// ==================================================================
function generate_map_data() {
// -------------------------------------------------------------
// --- Fill the $map array with values identifying the terrain
// --- type in each hex. This example simply randomizes the
// --- contents of each hex. Your code could actually load the
// --- values from a file or from a database.
// -------------------------------------------------------------
global $MAP_WIDTH, $MAP_HEIGHT;
global $map, $terrain_images;
for ($x=0; $x<$MAP_WIDTH; $x++) {
for ($y=0; $y<$MAP_HEIGHT; $y++) {
// --- Randomly choose a terrain type from the terrain
// --- images array and assign to this coordinate.
$map[$x][$y] = array_rand($terrain_images);
}
}
}
// ==================================================================
function render_map_to_html() {
// -------------------------------------------------------------
// --- This function renders the map to HTML. It uses the $map
// --- array to determine what is in each hex, and the
// --- $terrain_images array to determine what type of image to
// --- draw in each cell.
// -------------------------------------------------------------
global $MAP_WIDTH, $MAP_HEIGHT;
global $HEX_HEIGHT, $HEX_SCALED_HEIGHT, $HEX_SIDE;
global $map, $terrain_images;
// -------------------------------------------------------------
// --- Draw each hex in the map
// -------------------------------------------------------------
for ($x=0; $x<$MAP_WIDTH; $x++) {
for ($y=0; $y<$MAP_HEIGHT; $y++) {
// --- Terrain type in this hex
$terrain = $map[$x][$y];
// --- Image to draw
$img = $terrain_images[$terrain];
// --- Coordinates to place hex on the screen
$tx = $x * $HEX_SIDE * 1.5;
$ty = $y * $HEX_SCALED_HEIGHT + ($x % 2) * $HEX_SCALED_HEIGHT / 2;
// --- Style values to position hex image in the right location
$style = sprintf("left:%dpx;top:%dpx", $tx, $ty);
// --- Output the image tag for this hex
print "<img src='$img' alt='$terrain' class='hex' style='zindex:99;$style'>\n";
}
}
}
// -----------------------------------------------------------------
// --- Generate the map data
// -----------------------------------------------------------------
generate_map_data();
?>
<h1>Hex Map Example</h1>
<a href='index.phps'>View page source</a><br/>
<a href='hexmap.zip'>Download source and all images</a>
<!-- Render the hex map inside of a div block -->
<div id='hexmap' class='hexmap' onclick='handle_map_click(event);'>
<?php render_map_to_html(); ?>
<img id='highlight' class='hex' src='hex-highlight.png' style='zindex:100;'>
</div>
<!--- output a list of all terrain types -->
<br/>
<?php
reset ($terrain_images);
while (list($type, $img) = each($terrain_images)) {
print "<div class='hex-key-element'><img src='$img' alt='$type'><br/>$type</div>";
}
?>
</body>
</html>
Voici une capture d'écran de l'exemple ...
Pourrait certainement utiliser certaines améliorations. J'ai remarqué dans un commentaire précédent que vous aviez dit que vous connaissiez jQuery, ce qui est bien. Je ne l'ai pas utilisé ici pour garder les choses simples, mais ce serait assez utile à utiliser.
Vous devez écrire un petit moteur de disposition de tuiles javascript qui mappe les coordonnées des tuiles de la base de données dans une vue sur la page Web, car cela vous permet d'externaliser le temps de traitement du processeur à l'ordinateur du joueur. Ce n'est pas difficile à faire et vous pouvez le faire en quelques pages de code.
Donc, essentiellement, vous allez écrire une fine couche de PHP dont le seul but est de fournir des données de coordonnées au client à partir de votre base de données, de préférence en réponse à l'appel AJAX de votre page Web. Vous utiliserez probablement un format de données JSON pour une analyse facile, puis la partie de génération et d'affichage de la carte sera écrite en javascript et exécutée sur le client à l'aide d'une bibliothèque comme jQuery comme suggéré par numo16. Cette partie est relativement facile à faire et les mêmes concepts s'appliquent que dans les applications de jeu réel, donc la liste d'articles sur les canards communistes vous expliquera la partie d'affichage hexadécimale.
Pour l'affichage des graphiques de carte sur l'écran des joueurs, je vous recommande d'utiliser la technique CSS Sprites qui vous permet de stocker toutes vos tuiles de carte dans un seul fichier. Pour le positionnement, vous utiliseriez des coordonnées absolues pour l'image de tuile enveloppée dans un div, qui se trouvent à nouveau dans un div de conteneur relativement positionné.
Si vous appliquez des événements de clic jQuery à ces divs d'habillage d'image, vous pouvez rendre la carte cliquable facilement sans avoir à suivre manuellement les positions de la souris comme suggéré. Stylez la div du conteneur avec un écrêtage de débordement pour couper les bords de la carte pour qu'ils soient carrés au lieu des tuiles hexagonales de ligne dentelée pour rendre la carte belle. :)
la source
Mes pensées sont que lorsque les données sont lues dans la base de données, chaque tuile sera créée comme une image carrée avec une carte d'image hexagonale dans la position spécifiée par votre point (x, y). Ce qui signifie que vous devrez créer vos images de tuiles sous forme d'hexagones avec un canal alpha vide environnant, afin que vous puissiez chevaucher un peu vos tuiles pour les faire sembler s'emboîter. Vous voudrez peut-être examiner jQuery pour aider à peaufiner le côté graphique et l'interface utilisateur des choses (animation, ajax plus rapide et plus facile, gestion facile des événements, etc.).
la source
J'ai peur de ne pas parler PHP, donc je ne peux pas faire d'exemples de code. Cependant, voici une belle liste de ressources qui peuvent vous aider. :)
Voici une belle liste d'articles de grille isométrique / hexagonale sur Gamedev; allant de la façon de traiter les coordonnées hexagonales à mise cache des tuiles . (Bien sûr, certaines choses ne seront pas pertinentes car c'est surtout ... quel est le mot? Sur un PC pas un navigateur Web.)
Quant à l'affichage graphique, ajoutez simplement de la transparence à une image carrée d'une tuile hexagonale.
«Cliquable» serait quelque chose comme:
Je n'ai aucune idée de la quantité d'événements utilisateur et de la connexion de bases de données à PHP, vous devrez donc peut-être chercher d'autres langages et cadres pour cela.
Je te souhaite bonne chance. :)
la source
Suite à l'approche de Fuu, j'ai une version qui fonctionne uniquement sur javascript et jQuery dans le navigateur pour rendre la carte hexadécimale. À l'heure actuelle, il existe une fonction qui génère une structure de carte aléatoire en JSON (sur deux tuiles possibles) plus ou moins comme ceci:
var map = [["océan," désert "," désert "], [" désert, "désert", "océan"], ["océan," désert "," océan "]]]
... mais il est facile d'imaginer que la page Web émette un appel Ajax pour obtenir une telle structure de carte à partir d'un serveur au lieu de générer le code lui-même.
Le code est sur jsfiddle , d'où vous pouvez également trouver un lien vers un article de blog l'expliquant, et un lien github si vous êtes intéressé.
la source