# Understanding hexagonal tiles – updated with HTML5 examples thanks to Phaser

This is the update to a post I started a loooong time ago, back in 2008 with Understanding hexagonal tiles where I talked about – guess what – hexagonal tiles and above all about the difference from horizontal hexagonal tiles and vertical hexagonal tiles.

There is a lot of more theory and some ActionScript examples in the posts Hex maps creation and rollover, Finding adjacent cells in an hex map, Finding adjacent cells in an hex map – part 2 and Finding adjacent cells in an hex map – AS3 Version where all the theory behind hex maps is explained.

Now I am showing you how to create an hex map, both horizontal and vertical, center it on the stage and how to detect which hexagon you are moving the mouse over just using math. This way you should be able to port these scripts in any language you need.

Vertical hex maps

Here it is the example, move the mouse over the hexagons to place a marker on them:

And this is the source code:

```window.onload = function() {

var game = new Phaser.Game(640, 480, Phaser.CANVAS, "", {preload: onPreload, create: onCreate});

var hexagonWidth = 80;
var hexagonHeight = 70;
var gridSizeX = 10;
var gridSizeY = 12;
var columns = [Math.ceil(gridSizeY/2),Math.floor(gridSizeY/2)];
var moveIndex;
var sectorWidth = hexagonWidth/4*3;
var sectorHeight = hexagonHeight;
var marker;
var hexagonGroup;

}

function onCreate() {
game.stage.backgroundColor = "#ffffff"
for(var i = 0; i < gridSizeX/2; i ++){
for(var j = 0; j < gridSizeY; j ++){
if(gridSizeX%2==0 || i+1<gridSizeX/2 || j%2==0){
var hexagonX = hexagonWidth*i*1.5+(hexagonWidth/4*3)*(j%2);
var hexagonY = hexagonHeight*j/2;
}
}
}
hexagonGroup.y = (game.height-hexagonHeight*Math.ceil(gridSizeY/2))/2;
if(gridSizeY%2==0){
hexagonGroup.y-=hexagonHeight/4;
}
hexagonGroup.x = (game.width-Math.ceil(gridSizeX/2)*hexagonWidth-Math.floor(gridSizeX/2)*hexagonWidth/2)/2;
if(gridSizeX%2==0){
hexagonGroup.x-=hexagonWidth/8;
}
marker.anchor.setTo(0.5);
marker.visible=false;
}

function checkHex(){
var candidateX = Math.floor((game.input.worldX-hexagonGroup.x)/sectorWidth);
var candidateY = Math.floor((game.input.worldY-hexagonGroup.y)/sectorHeight);
var deltaX = (game.input.worldX-hexagonGroup.x)%sectorWidth;
var deltaY = (game.input.worldY-hexagonGroup.y)%sectorHeight;
if(candidateX%2==0){
candidateX--;
candidateY--;
}
candidateX--;
}
}
else{
if(deltaY>=hexagonHeight/2){
candidateX--;
}
}
else{
candidateX--;
}
else{
candidateY--;
}
}
}
placeMarker(candidateX,candidateY);
}

function placeMarker(posX,posY){
if(posX<0 || posY<0 || posX>=gridSizeX || posY>columns[posX%2]-1){
marker.visible=false;
}
else{
marker.visible=true;
marker.x = hexagonWidth/4*3*posX+hexagonWidth/2;
marker.y = hexagonHeight*posY;
if(posX%2==0){
marker.y += hexagonHeight/2;
}
else{
marker.y += hexagonHeight;
}
}
}

}```

And this now the same concept applied to…

Horizontal hex maps

Just like in previous example, move the mouse over the hexagons to place a marker:

And this is the – pretty similar – source code:

```window.onload = function() {

var game = new Phaser.Game(640, 480, Phaser.CANVAS, "", {preload: onPreload, create: onCreate});

var hexagonWidth = 70;
var hexagonHeight = 80;
var gridSizeX = 17;
var gridSizeY = 7;
var columns = [Math.ceil(gridSizeX/2),Math.floor(gridSizeX/2)];
var moveIndex;
var sectorWidth = hexagonWidth;
var sectorHeight = hexagonHeight/4*3;
var marker;
var hexagonGroup;

}

function onCreate() {
game.stage.backgroundColor = "#ffffff"
for(var i = 0; i < gridSizeY/2; i ++){
for(var j = 0; j < gridSizeX; j ++){
if(gridSizeY%2==0 || i+1<gridSizeY/2 || j%2==0){
var hexagonX = hexagonWidth*j/2;
var hexagonY = hexagonHeight*i*1.5+(hexagonHeight/4*3)*(j%2);
}
}
}
hexagonGroup.x = (game.width-hexagonWidth*Math.ceil(gridSizeX/2))/2;
if(gridSizeX%2==0){
hexagonGroup.x-=hexagonWidth/4;
}
hexagonGroup.y = (game.height-Math.ceil(gridSizeY/2)*hexagonHeight-Math.floor(gridSizeY/2)*hexagonHeight/2)/2;
if(gridSizeY%2==0){
hexagonGroup.y-=hexagonHeight/8;
}
marker.anchor.setTo(0.5);
marker.visible=false;
}

function checkHex(){
var candidateX = Math.floor((game.input.worldX-hexagonGroup.x)/sectorWidth);
var candidateY = Math.floor((game.input.worldY-hexagonGroup.y)/sectorHeight);
var deltaX = (game.input.worldX-hexagonGroup.x)%sectorWidth;
var deltaY = (game.input.worldY-hexagonGroup.y)%sectorHeight;
if(candidateY%2==0){
candidateX--;
candidateY--;
}
candidateY--;
}
}
else{
if(deltaX>=hexagonWidth/2){
candidateY--;
}
}
else{
candidateY--;
}
else{
candidateX--;
}
}
}
placeMarker(candidateX,candidateY);
}

function placeMarker(posX,posY){
if(posX<0 || posY<0 || posY>=gridSizeY || posX>columns[posY%2]-1){
marker.visible=false;
}
else{
marker.visible=true;
marker.x = hexagonWidth*posX;
marker.y = hexagonHeight/4*3*posY+hexagonHeight/2;
if(posY%2==0){
marker.x += hexagonWidth/2;
}
else{
marker.x += hexagonWidth;
}
}
}

}```

215 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 10000000
// 2 Cars
// 2048
// Avoider
// Ballz
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Breakout
// Bricks
// Columns
// CubesOut
// Dots
// DROP'd
// Dudeski
// Eskiv
// Filler
// Fling
// Globe
// HookPod
// Hundreds
// InkTd
// Iromeku
// Lumines
// Magick
// MagOrMin
// Maze
// Memdot
// Nano War
// Nodes
// o:anquan
// Ononmin
// Pacco
// Phyballs
// Platform
// Poker
// Pool
// Poux
// Pudi
// qomp
// Racing
// Renju
// SameGame
// Security
// Sling
// Slingy
// Sokoban
// Splitter
// Sproing
// Stack
// Stairs
// Stringy
// Sudoku
// Tetris
// Threes
// Toony
// Turn
// TwinSpin
// vvvvvv
// Wordle
// Worms
// Yanga
// Zhed
// zNumbers