* Редактировать: исправлена ошибка в javascript, приводившая к ошибке на firefox *
Редактировать: только что добавлена возможность масштабировать гексы в исходном коде PHP. Крошечные 1/2 размера или 2x джамбо, все зависит от вас :)
Я не совсем знал, как все это написать, но обнаружил, что было проще написать код для полного живого примера. Страница (ссылка и источник ниже) динамически генерирует шестнадцатеричную карту с помощью PHP и использует Javascript для обработки щелчков карты. Нажатие на гекс выделяет гекс.
Карта генерируется случайным образом, но вы должны иметь возможность использовать свой собственный код вместо этого, чтобы заполнить карту. Он представлен простым двумерным массивом, где каждый элемент массива содержит тип местности, представленной в этом гексе.
Нажмите меня, чтобы попробовать Пример шестнадцатеричной карты
Чтобы использовать, нажмите на любой гекс, чтобы выделить его.
Прямо сейчас он генерирует карту 10х10, но вы можете изменить размер карты в PHP так, чтобы он был любым. Я также использую набор плиток из игры Wesnoth для примера. Они имеют высоту 72x72 пикселя, но источник также позволяет вам устанавливать размер ваших шестнадцатеричных плиток.
Гексы представлены изображениями в формате PNG с прозрачными областями «вне гексагона». Чтобы расположить каждый гекс, я использую CSS, чтобы установить абсолютную позицию каждой плитки, рассчитанную по координатам сетки гекса. Карта заключена в один DIV, что облегчит вам модификацию примера.
Вот полный код страницы. Вы также можете скачать демо-источник (включая все шестнадцатеричные изображения).
<?php
// ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// :: HEX.PHP
// ::
// :: Author:
// :: Tim Holt, tim.m.holt@gmail.com
// :: 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>
Вот скриншот с примером ...
Определенно можно использовать некоторые улучшения. В предыдущем комментарии я заметил, что вы сказали, что знакомы с jQuery, и это хорошо. Я не использовал это здесь для простоты, но это было бы довольно полезно для использования.
Вам следует написать небольшой механизм компоновки мозаики javascript, который отображает координаты мозаики базы данных в представление на веб-странице, поскольку это позволяет передавать время обработки ЦП на компьютер игроков. Это не сложно, и вы можете сделать это за несколько страниц кода.
По сути, вы будете писать тонкий слой PHP, единственной целью которого является доставка координатных данных клиенту из вашей базы данных, предпочтительно в ответ на вызов AJAX с вашей веб-страницы. Скорее всего, вы будете использовать формат данных JSON для простого анализа, и тогда часть, генерирующая и отображающая карту, будет написана на javascript и выполнена на клиенте с использованием библиотеки, подобной jQuery, как это предложено в numo16. Эта часть сравнительно проста, и применимы те же понятия, что и в реальных игровых приложениях, поэтому список статей «Коммунистические утки» объяснит вам часть отображения гексагона.
Для отображения графики карты на экране проигрывателя я бы порекомендовал использовать технику CSS Sprites , которая позволяет хранить все плитки карты в одном файле. Для позиционирования вы должны использовать абсолютные координаты для мозаичного изображения, заключенного в div, которые снова находятся в относительно позиционированном контейнере div.
Если вы примените события кликов jQuery к этим div-элементам обтекания изображений, вы сможете легко сделать карту кликабельной без необходимости вручную отслеживать положения мыши, как это предлагается. Стилизируйте контейнерный блок с помощью переполнения, чтобы обрезать края карты, чтобы они были квадратными, а не шестигранными плитками с неровными линиями, чтобы карта выглядела красиво. :)
источник
Я думаю, что когда данные считываются из базы данных, каждая плитка будет создаваться в виде квадратного изображения с гексагональной картой изображений в любом положении, указанном вашей точкой (x, y). Это означает, что вам нужно будет создавать свои мозаичные изображения в виде шестиугольников с окружающим пустым альфа-каналом, так что вы можете немного перекрывать свои мозаичные изображения, чтобы они выглядели вместе. Возможно, вы захотите взглянуть на jQuery, чтобы помочь отточить графические аспекты и аспекты пользовательского интерфейса (анимация, более быстрый и легкий ajax, удобная обработка событий и т. Д.).
источник
Боюсь, я не говорю на PHP, поэтому я не могу делать примеры кода. Тем не менее, вот хороший список ресурсов, которые могут вам помочь. :)
Вот хороший список статей изометрической / гексагональной сетки на Gamedev; начиная от того, как обращаться с гексагональными координатами, до кэширования тайлов . (Конечно, некоторые вещи не будут актуальны, так как это в основном ... что за слово? На ПК, а не в веб-браузере.)
Что касается графического отображения, просто добавьте прозрачность к квадратному изображению шестиугольной плитки.
«Clickable» будет что-то вроде:
Я понятия не имею о том, как много пользовательских событий и подключение базы данных к PHP имеет, поэтому вам, возможно, придется поискать другие языки и платформы для этого.
Желаю тебе удачи. :)
источник
Следуя подходу Фуу, у меня есть работающая версия, которая полагается исключительно на javascript и jQuery в браузере для отображения шестнадцатеричной карты. Прямо сейчас есть функция, которая генерирует случайную структуру карты в JSON (из двух возможных плиток) примерно так:
var map = [["океан," пустыня "," пустыня "], [" пустыня, "пустыня", "океан"], ["океан," пустыня "," океан "]]
... но легко представить, что веб-страница выдает Ajax-вызов, чтобы получить такую структуру карты с сервера, а не генерировать сам код.
Код работает на jsfiddle , откуда вы также можете найти ссылку на пост в блоге, объясняющий это, и ссылку на github, если вам интересно.
источник