I'm trying to create a hexagon world map for my PHP browser based strategy game. I've created a table in my database with the following data per row: id, type, x, y and occupied. Where type is the kind of tiles, which are defined in numbers. For example, 1 is grass. The map itself is 25 x 25.
I want to draw the map from the database with clickable tiles and the possibilty to navigate through the map with arrows. I don't really have a clue on how to start with this and any help would be appreciated.
Answer
*Edit: Fixed error in javascript that caused error on firefox *
Edit: just added ability to scale hexes to the PHP source code. Tiny 1/2 sized ones or 2x jumbo, it's all up to you :)
I wasn't quite sure how to put this all into writing, but found it was easier to just write the code for a full live example. The page (link and source below) dynamically generates a hexmap with PHP and uses Javascript to handle map clicks. Clicking on a hex highlights the hex.
The map is randomly generated, but you should be able to use your own code instead to populate the map. It is represented by a simple 2d array, with each array element holding the type of terrain present in that hex.
Click me to try the Hex Map Example
To use, click on any hex to highlight it.
Right now it's generating a 10x10 map, but you can change the map size in the PHP to be any size you want. I'm also using a set of tiles from the game Wesnoth for the example. They are 72x72 pixels in height, but the source also lets you set the size of your hex tiles.
The hexes are represented by PNG images with "outside the hex" areas set as transparent. To position each hex, I am using CSS to set each tile's absolute position, calculated by the hex grid coordinate. The map is enclosed in a single DIV, which should make it easier for you to modify the example.
Here is the full page code. You can also download the demo source (including all hex images).
// ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// :: 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;
?>
Hex Map Demo
// ----------------------------------------------------------------------
// --- 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 "\n";
}
}
}
// -----------------------------------------------------------------
// --- Generate the map data
// -----------------------------------------------------------------
generate_map_data();
?>
Hex Map Example
View page source
Download source and all images
reset ($terrain_images);
while (list($type, $img) = each($terrain_images)) {
print "
$type";
}
?>
Here is a screenshot of the example...
Definitely could use some improvements. I noticed in a previous comment you said you were familiar with jQuery, which is good. I didn't use it here to keep things simple, but it would be pretty useful to use.
No comments:
Post a Comment