I have a 2D grid of squares. When I click the mouse I can easily determine which square the mouse was in with some division
Now I want to move to a 2D hexagon grid and be able to tell which hexagon the mouse pointer is in? How would I do this? Is there a formula for calculating this?
hexagon grid?
You can follow this article for regular hexagons:
http://www.gamedev.net/reference/articl ... le1800.asp
I think it has a bug somewhere in the pseudocode, but cant remember where or what affected.
Or take a look at my own calculation for non-regular hexagons:
that uses this code to get the work for a scrolling map:
Thats the game working with scroll:
I could port it to Java, so it is also working for a totally scrollable map (this means it can scroll to any pixel, instead of scrolling by 1 cell step):
http://www.gamedev.net/reference/articl ... le1800.asp
I think it has a bug somewhere in the pseudocode, but cant remember where or what affected.
Or take a look at my own calculation for non-regular hexagons:
that uses this code to get the work for a scrolling map:
Code: Select all
// ****************** //
// pixel2tile //
// ****************** //
// Calculate the tile where mouse pointer lays. This function should
// only be invoked if pointer is inside map area. Test for the area
// has to be made out of this function
// x, y are pixel coordinates (window, not map)
// Stores calculated coordinates in tileRow and tileCol pointers
void GRender::pixel2Tile(int initRow, int initCol, int x, int y, int* tileRow, int* tileCol) {
int r = HEX_SIZE/4;
int wW = 6*r, wH = 8*r;
int finalR, finalC; // Row and Col tile offsets inside aux window
// Let other methods do the hard work
x -= mapx;
y -= mapy;
if(initCol & 1) {
window2Tile4Odd(&finalR, &finalC, x, y);
} else {
window2Tile4Even(&finalR, &finalC, x, y);
}
(*tileRow) = (y / wH)*2 + finalR + initRow;
(*tileCol) = (x / wW)*2 + finalC + initCol;
}
// ******************** //
// window2Tile4Even //
// ******************** //
// Explore auxiliar window intervals and store relative tile
// coordinates in finalR and finalC
// Zones in this method apply to maps starting with even column on index 0
// x, y are coordinates inside map (mapx -> mapw and mapy -> maph axis)
void GRender::window2Tile4Even(int* finalR, int* finalC, int x, int y) {
// Useful vars
int r = HEX_SIZE/4, so_3r = 3*r, so_2r = 2*r, so_4r = HEX_SIZE;
int so_6r = 6*r, so_8r = HEX_SIZE*2;
int remX = x % (6*r), remY = y % (8*r); // Remainders inside window
int p2tOffset = 4; // adjust pixel scale to easy integer geometry
// Check X inside window interval
if(remX<r) { // x [ 0 - r)
remX = MAX(1, remX - p2tOffset);
// Y intervals
if(remY<so_2r) { // y [ 0 - 2r)
remY = so_2r-remY;
if((remY/remX) > 2) {
(*finalR) = -1;
(*finalC) = -1;
} else {
(*finalR) = 0;
(*finalC) = 0;
}
} else if(remY<so_4r) { // y [2r - 4r)
remY = so_2r-remY;
if((remY/remX) < -2) {
(*finalR) = 0;
(*finalC) = -1;
} else {
(*finalR) = 0;
(*finalC) = 0;
}
} else if(remY<so_6r) { // y [4r - 6r)
remY = so_6r-remY;
if((remY/remX) > 2) {
(*finalR) = 0;
(*finalC) = -1;
} else {
(*finalR) = 1;
(*finalC) = 0;
}
} else { // y [6r - 8r)
remY = so_6r-remY;
if((remY/remX) < -2) {
(*finalR) = 1;
(*finalC) = -1;
} else {
(*finalR) = 1;
(*finalC) = 0;
}
}
} else if(remX<so_3r) { // x [ r - 3r)
// Y intervals
if(remY<so_4r) { // y [ 0 - 4r)
(*finalR) = 0;
(*finalC) = 0;
} else { // y [4r - 8r)
(*finalR) = 1;
(*finalC) = 0;
}
} else if(remX<so_4r) { // x [3r - 4r)
remX = MAX(1, remX - so_3r - p2tOffset);
// Y intervals
if(remY<so_2r) { // y [ 0 - 2r)
remY = 0-remY;
if((remY/remX) < -2) {
(*finalR) = 0;
(*finalC) = 0;
} else {
(*finalR) = -1;
(*finalC) = 1;
}
} else if(remY<so_4r) { // y [2r - 4r)
remY = so_4r-remY;
if((remY/remX) > 2) {
(*finalR) = 0;
(*finalC) = 0;
} else {
(*finalR) = 0;
(*finalC) = 1;
}
} else if(remY<so_6r) { // y [4r - 6r)
remY = so_4r-remY;
if((remY/remX) < -2) {
(*finalR) = 1;
(*finalC) = 0;
} else {
(*finalR) = 0;
(*finalC) = 1;
}
} else { // y [6r - 8r)
remY = so_8r-remY;
if((remY/remX) > 2) {
(*finalR) = 1;
(*finalC) = 0;
} else {
(*finalR) = 1;
(*finalC) = 1;
}
}
} else { // x [4r - 6r)
// Y intervals
if(remY<so_2r) { // y [ 0 - 2r)
(*finalR) = -1;
(*finalC) = 1;
} else if(remY<so_6r) { // y [2r - 6r)
(*finalR) = 0;
(*finalC) = 1;
} else { // y [6r - 8r)
(*finalR) = 1;
(*finalC) = 1;
}
}
}
// ******************** //
// window2Tile4Odd //
// ******************** //
// Explore auxiliar window intervals and store relative tile
// coordinates in finalR and finalC
// Zones in this method apply to maps starting with odd column on index 0
// x, y are coordinates inside map (mapx -> mapw and mapy -> maph axis)
void GRender::window2Tile4Odd(int* finalR, int* finalC, int x, int y) {
// Useful vars
int r = HEX_SIZE/4, so_3r = 3*r, so_2r = 2*r, so_4r = HEX_SIZE;
int so_6r = 6*r, so_8r = HEX_SIZE*2;
int remX = x % (6*r), remY = y % (8*r); // Remainders inside window
int p2tOffset = 4; // adjust pixel scale to easy integer geometry
// Check X inside window interval
if(remX<r) { // x [ 0 - r)
remX = MAX(1, remX - p2tOffset);
// Y intervals
if(remY<so_2r) { // y [ 0 - 2r)
remY = 0-remY;
if((remY/remX) < -2) {
(*finalR) = 0;
(*finalC) = -1;
} else {
(*finalR) = -1;
(*finalC) = 0;
}
} else if(remY<so_4r) { // y [2r - 4r)
remY = so_4r-remY;
if((remY/remX) > 2) {
(*finalR) = 0;
(*finalC) = -1;
} else {
(*finalR) = 0;
(*finalC) = 0;
}
} else if(remY<so_6r) { // y [4r - 6r)
remY = so_4r-remY;
if((remY/remX) < -2) {
(*finalR) = 1;
(*finalC) = -1;
} else {
(*finalR) = 0;
(*finalC) = 0;
}
} else { // y [6r - 8r)
remY = so_8r-remY;
if((remY/remX) > 2) {
(*finalR) = 1;
(*finalC) = -1;
} else {
(*finalR) = 1;
(*finalC) = 0;
}
}
} else if(remX<so_3r) { // x [ r - 3r)
// Y intervals
if(remY<so_2r) { // y [ 0 - 2r)
(*finalR) = -1;
(*finalC) = 0;
} else if(remY<so_6r) { // y [ 0 - 6r)
(*finalR) = 0;
(*finalC) = 0;
} else { // y [6r - 8r)
(*finalR) = 1;
(*finalC) = 0;
}
} else if(remX<so_4r) { // x [3r - 4r)
remX = MAX(1, remX - so_3r - p2tOffset);
// Y intervals
if(remY<so_2r) { // y [ 0 - 2r)
remY = so_2r-remY;
if((remY/remX) > 2) {
(*finalR) = -1;
(*finalC) = 0;
} else {
(*finalR) = 0;
(*finalC) = 1;
}
} else if(remY<so_4r) { // y [2r - 4r)
remY = so_2r-remY;
if((remY/remX) < -2) {
(*finalR) = 0;
(*finalC) = 0;
} else {
(*finalR) = 0;
(*finalC) = 1;
}
} else if(remY<so_6r) { // y [4r - 6r)
remY = so_6r-remY;
if((remY/remX) > 2) {
(*finalR) = 0;
(*finalC) = 0;
} else {
(*finalR) = 1;
(*finalC) = 1;
}
} else { // y [6r - 8r)
remY = so_6r-remY;
if((remY/remX) < -2) {
(*finalR) = 1;
(*finalC) = 0;
} else {
(*finalR) = 1;
(*finalC) = 1;
}
}
} else if(remX<so_6r) { // x [4r - 6r)
// Y intervals
if(remY<so_4r) { // y [ 0 - 4r)
(*finalR) = 0;
(*finalC) = 1;
} else { // y [4r - 8r)
(*finalR) = 1;
(*finalC) = 1;
}
}
}
I could port it to Java, so it is also working for a totally scrollable map (this means it can scroll to any pixel, instead of scrolling by 1 cell step):
First one is a modified image, not a real screenshot.
Second one is the game done with Allegro Library (not irrlicht)
Last one is done with Java Swing.
Second one is the game done with Allegro Library (not irrlicht)
Last one is done with Java Swing.
Warchief's Warboard 3D Now hotseat release