проблема рисования шестиугольной сетки

Кажется, у меня возникли проблемы с рисованием правильной шестнадцатеричной сетки:

Кажется, все в порядке misaligned

Как видите, шестиугольники немного смещены, хотя я считаю, что моя математика верна (некоторые из них проверены через 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

На первый взгляд, я думаю, что проблема связана с математической точностью с плавающей запятой, хотя я не уверен, как это исправить/улучшить.

Любые идеи?

Я знаю, что мой метод рисования приведет к большому количеству перекрывающихся линий, и на данный момент это нормально. Если это поможет, общий код предназначен для генератора шестиугольного лабиринта, который работает нормально, и поэтому его можно игнорировать, поскольку он не является частью проблемы.

И если это поможет, я храню шестиугольные плитки только в одном длинном массиве, проиндексированном следующим образом:

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

person mitim    schedule 24.10.2016    source источник
comment
Хотя это и не желательно для вашего конечного продукта, попробуйте изменить все ваши значения int на значения Num. Посмотрите, что происходит. Также сосредоточьтесь на своем коде, который имеет дело с позицией X каждой новой плитки.   -  person Neal Davis    schedule 24.10.2016
comment
... э... это сработало. Я не знаю почему. =| Я только что сделал глобальную замену целых чисел на числа, и это сработало. Хм, вернусь и заменю вручную, чтобы увидеть, какая именно переменная int это сделала.   -  person mitim    schedule 24.10.2016
comment
Ой! Я понял. В drawHexTile() я установил inputX и inputY как типы int. Но на самом деле вычисляемые позиции были значениями с плавающей запятой, поэтому они округлялись до целых, что неявно вызывало смещение. Простая ошибка (рефлекторно), в конце концов, никакого волшебства в исправлении нет. Если вы сделаете репост своего комментария в качестве ответа, я отмечу его как принятый.   -  person mitim    schedule 24.10.2016


Ответы (2)


Хотя это и не желательно для вашего конечного продукта, попробуйте изменить все ваши значения int на значения Num. Посмотрите, что происходит. Также сосредоточьтесь на своем коде, который имеет дело с позицией X каждой новой плитки.

из ваших комментариев

... э... это сработало. Я не знаю почему. =| Я только что сделал глобальную замену целых чисел на числа, и это сработало. Хм, вернусь и заменю вручную, чтобы увидеть, какая именно переменная int это сделала.

Ой! Я понял. В drawHexTile() я установил inputX и inputY как типы int. Но на самом деле вычисляемые позиции были значениями с плавающей запятой, поэтому они округлялись до целых, что неявно вызывало смещение. Простая ошибка (рефлекторно), в конце концов, никакого волшебства в исправлении нет.

person Neal Davis    schedule 24.10.2016

Похоже на проблему с плавающей запятой в вашем 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)));
person Philarmon    schedule 24.10.2016
comment
Я тоже так пробовал. Пол, закругление, потолок и т. д. в различных точках как для рисования, так и для позиционирования плитки. Я не вижу никакой закономерности в интервалах - person mitim; 24.10.2016