hexagon grid drawing issue

mitim picture mitim · Oct 24, 2016 · Viewed 7k times · Source

I seem to be having a bit of trouble drawing a proper hex grid:

seems ok misaligned

As you can see, the hexagons are just slightly misaligned, though I believe my math is correct (some of which is verfied via http://www.redblobgames.com/grids/hexagons/).

My method of drawing is to start at the top left hexagon (first tile in the first row) and draw that row of tiles. Then for the next row, there is a negative X offset and positive Y offset, etc until it reaches the middle row, at which the X offsets increase until 0:

private function drawHexGrid(inputGraphics:Graphics, inputPos:Point, inputGrid:HexGrid, inputTileSize:int):void {

    var rootThree:Number = Math.sqrt(3); // seems like this will be used a lot

    // total number of rows and also size of largest row (in tiles)
    var totalRows:int = (2 * inputGrid.size) - 1;

    // the other useful dimension of a hex tile
    var triSize:Number = rootThree * 0.5 * inputTileSize;

    var topLeft:Point = new Point(-(inputGrid.size - 1) * triSize, -(1.5 * (inputGrid.size - 1) * inputTileSize));
    topLeft.x += inputPos.x;
    topLeft.y += inputPos.y;
    var currentPos:Point = topLeft.clone();

    // step size between each tile and row
    var xStep:Number = rootThree * inputTileSize;
    var yStep:Number = triSize * rootThree;

    var offsetDirection:int = -1;
    var rowLimit:int = inputGrid.size;
    var offsetAmount:int = 0; // offsetAmount goes 1 to n, then back to 0 again, used for calculating thw row offsets

    var mazeTiles:Vector.<Tile> = inputGrid.getTiles();
    var tileCounter:int = 0; // index to cycle through mazeTiles

    for(var rowCount:int = 0; rowCount < totalRows; rowCount++){
        currentPos.x = topLeft.x + (offsetAmount * rootThree / -2 * inputTileSize);

        for(var counter:int = 0; counter < rowLimit; counter++){
            drawHexTile(inputGraphics, currentPos.x, currentPos.y, inputTileSize, mazeTiles[tileCounter++]);
            currentPos.x += xStep;
        }

        currentPos.y += yStep;

        if(rowCount == (inputGrid.size - 1)){
            offsetDirection *= -1;
        }
        rowLimit += offsetDirection * -1;
        offsetAmount -= offsetDirection;

    } // end of for loop
} // end of drawHexGrid()

The actual drawing of each hexagon is in this loop:

private function drawHexTile(inputGraphics:Graphics, inputX:int, inputY:int, inputSize:int, inputTile:Tile):void {
    inputGraphics.lineStyle(0.1, 0, 1);

    var convertToRadians:Number = Math.PI / 180;

    // easier to draw by wall, since need to look up each wall and can set a starting degree without having to worry about the 'end degree'
    // (since the end may not be 360 degrees if the starting degree is in the negatives or a high degree)
    var degrees:int = -150; // starting wall is the top left wall of the hexagon tile
    for(var counter:int = 0; counter < 6; counter++){

        if(inputTile.walls[counter] == true){
            inputGraphics.moveTo(inputX + (Math.cos(degrees * convertToRadians) * inputSize), 
                                    inputY + (Math.sin(degrees * convertToRadians) * inputSize));

            inputGraphics.lineTo(inputX + (Math.cos((degrees + 60) * convertToRadians) * inputSize), 
                                    inputY + (Math.sin((degrees + 60) * convertToRadians) * inputSize));
        }
        degrees += 60;
    }

} // end of drawHexTile() method

At first glance, I think the issue is due to floating point math accuracy, though I'm not sure how to go about fixing/improving this.

Any ideas?

I am aware that my drawing method would end up with many overlapping lines, which is fine for the moment. If it helps, the overall code is meant for a hexagon maze generator, which is working fine and thus can be ignored as it isn't part of the problem.

And if it helps, how I am storing the hexagon tiles is just in one long array, indexed like this:

where n=4

             0       1       2       3
         4       5       6       7       8
     9      10      11      12      13      14   
15      16      17      18      19      20      21
    22      23      24      25      26      27   
        28      29      30      31      32
            33      34      35      36

Answer

Neal Davis picture Neal Davis · Oct 24, 2016

While not preferable for your final product, try changing all of your int values to Num values. See what happens. Also focus on your code that deals with the X position of each new tile.

from your comments

...uh.....this worked. I don't know why. =| I just did a global replace for ints to Numbers and it worked. Hm, will go back and manually replace to see exactly what int variable did it.

Oh! I figured it out. In drawHexTile() I had set inputX and inputY as int types. But in actuality, the positions being calculated were floating values, so they were being rounded to ints implicitly causing the misalignment. Simple mistake (by reflex), no magic involved after all in the fix.