PHP中的Bresenham线算法

时间:2016-11-20 23:42:02

标签: php algorithm oop multidimensional-array bresenham

我正在开发基于文本的(控制台)WW2策略游戏,设置在2d方格网格地图上。我想要一种方法来计算从地图上的一个图块到另一个图块的视线。我已经使用this Java示例来解决我的代码问题,这就是我所写的:

\"

注意:getEmptyMap只用0&#39填充多维数组。

Testresult使用(0,0,4,4,4)作为输入:

public function plotLine($x0, $y0, $x1, $y1, $size)
{   
    $arr = $this->getEmptyMap($size);
    $xDist = abs($x1 - $x0);
    $yDist = -abs($y1 - $y0);
    if($x0 < $x1) {
        $xStep = 1;
    } else {
        $xStep = -1;
    }

    if($y0 < $y1) {
        $yStep = 1;
    } else {
        $yStep = -1;
    }

    $plotError = $xDist + $yDist;

    $arr[$x0][$y0] = 1;

    while($x0 != $x1 || $y0 != $y1) {
        // if(2 * $plotError > $yDist) {
        //  // Horizontal step
        //  $plotError += $yDist;
        //  $x0 += $xStep;
        // }

        // if(2 * $plotError < $xDist) {
        //  // Vertical step
        //  $plotError += $xDist;
        //  $y0 += $yStep;
        // }

        if(2 * $plotError - $yDist > $xDist - 2 * $plotError) {
            // Horizontal step
            $plotError += $yDist;
            $x0 += $xStep;
        } else {
            // Vertical step
            $plotError += $xDist;
            $y0 += $yStep;
        }           


        $arr[$x0][$y0] = 1;
    }

    $this->line = $arr;
}

我尝试过绘制线的方法:一个是Franz D.使用的常规实现(目前在上面的示例中已经注释掉),另一个是Franz D.所展示的修改后的实现。也没有给我我想要的结果;一种&#34;抗锯齿&#34;。当焊料看起来从0,0,2,2和1,2和2,1处的建筑物时,2,2处的任何东西都应该被阻挡。注释掉的实施将完全忽略建筑物,修改确实会打击&#34; 2,1但不是1,2。如何将我的代码调整为&#34; hit&#34;在线下方和线上方?

1 个答案:

答案 0 :(得分:1)

您遇到的'问题'是因为在查看精确对角线时出现特殊边缘情况。处理这个问题只有两个(简单)的可能性:

1)对角线同时增加水平和垂直平铺。在你的游戏中,这意味着即使主要方向被阻挡,单位也能够看到对角线。

2)选择优先考虑水平图块或垂直图块,只增加两者之一。这是Franz D.的算法,你最后写了并放在你的帖子里。这里,if - 语句对于对角线是正确的,这意味着结果将是:

1100
0110
0011
0001

如果您希望竖线具有优先权,可以将其更改为:

...
        if(2 * $plotError - $yDist < $xDist - 2 * $plotError) {
            // Vertical step
            $plotError += $xDist;
            $y0 += $yStep; 
        } else {
          // Horizontal step
            $plotError += $yDist;
            $x0 += $xStep;
        }  

...

请注意,if / else的两个主体都已交换,>在条件中已更改为<

现在,结果将是:

1000
1100
0110
0011

如果你想让一个单位只能看到对角线,如果没有任何障碍阻挡相邻的红衣主教,那么最简单的解决办法就是使用上述两种算法,并将他们的结果合并为一个瓦片阵列。

最后一点说明:如果您只对坐标感兴趣而不是对它们的值感兴趣(就像您描述的用例的情况一样),使用简单的提取数组可能会更有效(内存) (x, y)坐标代替完整地图的二维数组,然后将其循环以提取结果为(x, y)的所有1坐标。

祝你好运!