回答:
*編集:Firefoxでエラーを引き起こしたJavaScriptのエラーを修正*
編集:ヘックスをPHPソースコードにスケーリングする機能を追加しました。小さな1/2サイズのものまたは2xジャンボ、それはあなた次第です:)
私はこれをすべて書く方法をよく知りませんでしたが、完全な実例のコードを書く方が簡単だとわかりました。このページ(以下のリンクとソース)は、PHPで16進マップを動的に生成し、Javascriptを使用してマップクリックを処理します。ヘックスをクリックすると、そのヘックスが強調表示されます。
マップはランダムに生成されますが、マップを作成する代わりに独自のコードを使用できる必要があります。それは単純な2D配列で表され、各配列要素はそのヘックスに存在する地形のタイプを保持します。
使用するには、任意のヘックスをクリックしてハイライトします。
現在、10x10マップを生成していますが、PHPのマップサイズを任意のサイズに変更できます。また、例としてゲームWesnothのタイルのセットを使用しています。高さは72x72ピクセルですが、ソースでは16進タイルのサイズも設定できます。
ヘックスは、「ヘックスの外側」領域が透明に設定されたPNG画像で表されます。各ヘクスを配置するには、CSSを使用して、各タイルの絶対位置を16進グリッド座標で計算して設定します。マップは単一の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に精通していると言っていましたが、これは良いことです。ここでは、物事を単純にするために使用しませんでしたが、使用すると非常に便利です。
データベースタイル座標をWebページ上のビューにマッピングする小さなJavaScriptタイルレイアウトエンジンを作成する必要があります。これにより、CPU処理時間をプレーヤーのコンピューターに外部委託できるようになります。難しくありません。数ページのコードで実行できます。
したがって、基本的には、データベースのクライアントに座標データを配信することだけが目的で、できればWebページからのAJAX呼び出しへの応答で、PHPの薄いレイヤーを作成します。JSONデータ形式を使用して簡単に解析し、マップ生成および表示部分をjavascriptで記述し、numo16で提案されているjQueryなどのライブラリを使用してクライアントで実行する可能性があります。この部分は比較的簡単に実行でき、実際のゲームアプリケーションと同じ概念が適用されるため、共産主義者のアヒルの記事のリストで、16進表示部分について説明します。
プレーヤー画面にマップグラフィックを表示するには、すべてのマップタイルを1つのファイルに保存できるCSSスプライトテクニックを使用することをお勧めします。配置には、divにラップされたタイルイメージの絶対座標を使用します。これも、比較的配置されたコンテナーdivにあります。
これらの画像ラッピングdivにjQueryクリックイベントを適用すると、推奨されるようにマウス位置を手動で追跡することなく、マップを簡単にクリック可能にすることができます。コンテナdivをスタイルし、オーバーフロークリッピングを使用して、マップの見栄えを良くするために、ぎざぎざの線の16進タイルではなく正方形になるようにマップのエッジをトリミングします。:)
PHPを話せないので、コード例を書くことはできません。ただし、役立つリソースのリストを以下に示します。:)
Gamedevの等尺性/六角形のグリッド記事の素晴らしいリストを以下に示します。至るまで、六角形COORDSに対処する方法にタイルをキャッシュします。(もちろん、WebブラウザではなくPC上での単語の意味がほとんどなので、一部のものは関連性がありません。)
グラフィック表示については、六角形タイルの正方形の画像に透明度を追加するだけです。
「クリック可能」は次のようになります。
if mouse button down on app:
take screen coordinates of mouse
Compare to screen coordinates of tiles
PHPに対するユーザーイベントとデータベースフックアップの方法がどれだけあるかはわかりません。そのためには、他の言語とフレームワークを調べる必要があるかもしれません。
私はあなたの幸運を祈ります。:)
Fuuのアプローチをフォローアップすると、16進マップをレンダリングするためにブラウザーのjavascriptとjQueryのみに依存するバージョンが動作します。現在、JSONで(2つの可能性のあるタイルから)多かれ少なかれこのようなランダムなマップ構造を生成する関数があります。
var map = [["ocean、" desert "、" desert "]、[" desert、 "desert"、 "ocean"]、["ocean、" desert "、" ocean "]]
...しかし、WebページがAjax呼び出しを発行して、コード自体を生成する代わりに、サーバーからそのようなマップ構造を取得することは簡単に想像できます。
コードはjsfiddleにあり、そこから、それを説明するブログ投稿へのリンクと、興味があるならgithubリンクを見つけることができます。