六边形网格绘图问题

hexagon grid drawing issue

我似乎在绘制合适的六角网格时遇到了一些麻烦:

如您所见,六边形稍微错位,但我相信我的数学是正确的(其中一些已通过 http://www.redblobgames.com/grids/hexagons/ 验证)。

我的画法是从左上角的六边形(第一行的第一个方块)开始画那一行方块。然后对于下一行,有负 X 偏移和正 Y 偏移等,直到到达中间行,此时 X 偏移增加直到 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()

每个六边形的实际绘制在这个循环中:

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

乍一看,我认为问题出在浮点数学精度上,但我不确定如何处理fixing/improving。

有什么想法吗?

我知道我的绘图方法最终会出现许多重叠的线条,暂时还好。如果有帮助,整个代码是针对六边形迷宫生成器的,它工作正常,因此可以忽略,因为它不是问题的一部分。

如果有帮助的话,我将六边形瓷砖存储在一个长数组中,索引如下:

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

您的 drawHexTile 中似乎存在浮点问题。您是否尝试过向下舍入您的绘图坐标以便始终拥有圆形像素坐标?像

inputGraphics.moveTo(Math.floor(inputX + (Math.cos(degrees * convertToRadians) * inputSize)), Math.floor(inputY + (Math.sin(degrees * convertToRadians) * inputSize)));

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

虽然这对您的最终产品来说并不可取,但请尝试将所有 int 值更改为 Num 值。走着瞧吧。还要关注处理每个新图块的 X 位置的代码。

来自您的评论

...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.