* Bearbeiten: Fehler in Javascript behoben, der Fehler bei Firefox verursachte *
Bearbeiten: Es wurde die Möglichkeit hinzugefügt, Hexes im PHP-Quellcode zu skalieren. Winzige 1/2 Größe oder 2x Jumbo, es liegt ganz bei dir :)
Ich war mir nicht ganz sicher, wie ich das alles schreiben sollte, fand es aber einfacher, den Code für ein vollständiges Live-Beispiel zu schreiben. Die Seite (Link und Quelle unten) generiert dynamisch eine Hexmap mit PHP und verwendet Javascript, um Kartenklicks zu verarbeiten. Ein Klick auf ein Hex hebt das Hex hervor.
Die Karte wird nach dem Zufallsprinzip generiert, aber Sie sollten stattdessen Ihren eigenen Code verwenden können, um die Karte zu füllen. Es wird durch ein einfaches 2d-Array dargestellt, wobei jedes Array-Element den in diesem Hex vorhandenen Geländetyp enthält.
Klicken Sie auf mich, um das Hex-Kartenbeispiel zu testen
Klicken Sie zur Verwendung auf ein beliebiges Hex, um es zu markieren.
Momentan wird eine 10x10-Karte erstellt, aber Sie können die Kartengröße in PHP so ändern, dass sie jeder gewünschten Größe entspricht. Für das Beispiel verwende ich auch eine Reihe von Kacheln aus dem Spiel Wesnoth. Sie haben eine Höhe von 72 x 72 Pixel, aber mit der Quelle können Sie auch die Größe Ihrer Hex-Kacheln festlegen.
Die Sechsecke werden durch PNG-Bilder dargestellt, wobei Bereiche "außerhalb des Sechsecks" als transparent festgelegt sind. Um jedes Hex zu positionieren, verwende ich CSS, um die absolute Position jeder Kachel festzulegen, die anhand der Hex-Gitterkoordinate berechnet wird. Die Karte ist in einem einzigen DIV enthalten, was Ihnen das Ändern des Beispiels erleichtern soll.
Hier ist der ganzseitige Code. Sie können auch die Demo-Quelle herunterladen (einschließlich aller Hex-Bilder).
<?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>
Hier ist ein Screenshot des Beispiels ...
Könnte auf jeden Fall einige Verbesserungen gebrauchen. Ich habe in einem früheren Kommentar bemerkt, dass Sie gesagt haben, Sie seien mit jQuery vertraut, was gut ist. Ich habe es hier nicht verwendet, um die Dinge einfach zu halten, aber es wäre ziemlich nützlich, es zu verwenden.
Sie sollten eine kleine JavaScript-Kachel-Layout-Engine schreiben, die die Datenbankkachelkoordinaten in einer Ansicht auf der Webseite abbildet, da Sie so die CPU-Verarbeitungszeit auf den Player-Computer auslagern können. Es ist nicht schwer zu tun und Sie können es in wenigen Seiten Code tun.
Im Grunde schreiben Sie also eine dünne PHP-Schicht, deren einziger Zweck darin besteht, dem Client Koordinatendaten aus Ihrer Datenbank zu übermitteln, vorzugsweise als Antwort auf einen AJAX-Aufruf von Ihrer Webseite. Sie würden wahrscheinlich ein JSON-Datenformat verwenden, um das Parsen zu vereinfachen, und dann würde der Kartengenerierungs- und -anzeigeteil in Javascript geschrieben und auf dem Client unter Verwendung einer Bibliothek wie jQuery ausgeführt, wie von numo16 vorgeschlagen. Dieser Teil ist relativ einfach zu machen und es gelten die gleichen Konzepte wie in echten Spieleanwendungen, so dass die Artikelliste der kommunistischen Enten Ihnen den hexadezimalen Anzeigeteil erklären wird.
Für die Anzeige von Kartengrafiken auf dem Player-Bildschirm empfehle ich die Verwendung der CSS-Sprites- Technik, mit der Sie alle Kartenkacheln in einer einzigen Datei speichern können. Für die Positionierung würden Sie absolute Koordinaten für das Kachelbild verwenden, das in ein div eingebunden ist. Diese befinden sich wiederum in einem relativ positionierten container div.
Wenn Sie jQuery-Klickereignisse auf diese Bildumbruch-Divs anwenden, können Sie die Karte einfach anklickbar machen, ohne die Mauspositionen wie vorgeschlagen manuell verfolgen zu müssen. Gestalten Sie das Container-Div mit einem Überlauf-Clipping, um die Kartenränder so zu kürzen, dass sie statt der gezackten Hex-Linienfliesen quadratisch sind, damit die Karte gut aussieht. :)
quelle
Ich bin der Meinung, dass beim Einlesen der Daten aus der Datenbank jede Kachel als quadratisches Bild mit einer hexagonalen Imagemap an der von Ihrem (x, y) -Punkt angegebenen Position erstellt wird. Das bedeutet, dass Sie Ihre Kachelbilder als Sechsecke mit einem umlaufenden leeren Alphakanal erstellen müssen, damit Sie Ihre Kacheln ein wenig überlappen können, damit sie zusammenpassen. Möglicherweise möchten Sie sich mit jQuery befassen, um die Grafiken und die Benutzeroberfläche (Animation, schnellere und einfachere Ajax-Funktion, einfache Ereignisbehandlung usw.) zu verbessern.
quelle
Ich spreche leider kein PHP und kann daher keine Codebeispiele erstellen. Hier ist jedoch eine schöne Liste von Ressourcen, die Ihnen helfen können. :)
Hier ist eine schöne Liste von isometrischen / hexagonalen Gitterartikeln auf Gamedev; angefangen vom Umgang mit hexagonalen Koordinaten bis hin zum Zwischenspeichern von Kacheln . (Natürlich sind einige Dinge nicht relevant, da es sich meistens um ... was ist das Wort? Auf einem PC kein Webbrowser.)
Fügen Sie für die grafische Anzeige einfach Transparenz zu einem quadratischen Bild einer hexagonalen Kachel hinzu.
"Klickbar" wäre so etwas wie:
Ich habe keine Ahnung, wie viel in Bezug auf Benutzerereignisse und die Anbindung von Datenbanken an PHP steckt, daher müssen Sie sich möglicherweise andere Sprachen und Frameworks dafür ansehen.
Ich wünsche Ihnen Glück. :)
quelle
Im Anschluss an Fuus Ansatz habe ich eine funktionierende Version, die sich ausschließlich auf Javascript und jQuery im Browser stützt, um die Hex-Karte zu rendern. Momentan gibt es eine Funktion, die in JSON eine zufällige Kartenstruktur erzeugt (aus zwei möglichen Kacheln), die ungefähr so aussieht:
var map = [["Ozean", "Wüste", "Wüste"], ["Wüste", "Ozean"], ["Ozean", "Wüste", "Ozean"]
... aber es ist leicht vorstellbar, dass die Webseite einen Ajax-Aufruf ausgibt, um eine solche Kartenstruktur von einem Server abzurufen, anstatt den Code selbst zu generieren.
Der Code ist auf jsfiddle verfügbar . Dort finden Sie auch einen Link zu einem Blog-Beitrag, der ihn erklärt, und einen Github-Link, wenn Sie interessiert sind.
quelle