计算周长值

时间:2011-10-25 13:37:43

标签: php geometry

我有一个矩形地图,存储为多维数组(即$map[row][col]),我必须追踪玩家看到哪些方块,放在这张地图上的任何位置。

玩家可见性是圆形的,半径未知(但在运行时给出)我只需要整数解。

我知道周长公式是

x^2 + y^2 <= r^2

但我怎么能存储一切?
我需要这些值,因为那时我可以“揭示”地图方块。


最好的是多维数组(即__$sol[x][y]__) 这是我正在使用的一段代码。它没有得到纠正,因为它假设视觉是正方形而不是圆形。

计算平方

$this->vision_offsets_2 = array();
//visibility given as r^2
$mx = (int)(sqrt($this->viewradius2));

$mxArr = range($mx * -1, $mx + 1);
foreach ($mxArr as $d_row)
{
    foreach ($mxArr as $d_col)
    {
         $this->vision_offsets_2[] = array($d_row, $d_col);
    }
}

这是我应用

的方式
    foreach($player as $bot)
    {
        foreach($visibility as $offset)
        {
            $vision_row = $offset[0] + $bot[0];
            $vision_col = $offset[1] + $bot[1];

            if(isset($map[$vision_row][$vision_col]))
            {
                if( $map[$vision_row][$vision_col] == UNSEEN) {
                    $map[$vision_row][$vision_col] =  LAND; }
            }
        }
    }

在这里你可以找到机器人视图:你可以看到一个非完美的圆圈 我该如何追踪?顺便说一下,在这个例子中,半径^ 2是55,橙色圆圈是玩家,棕色方块是可见的。

bot view

4 个答案:

答案 0 :(得分:1)

结构

您已经在网格中引用了地形。将地形对象存储在这些网格值中。将属性应用于这些对象。检查

之类的内容
$map[$x][$y]->isVisible($player);

你需要一些方法来设置视觉和测试,以检查用户是否可以看到它的用户列表。当你在这里时,在这些对象中设置其他相关方法(我看到对陆地的引用...... isLand()isWater()可能?)。

您甚至可以在对象内部进行视觉级联,这样您只需要移动用户的位置,并且该对象负责触发所有代码以将附近的地块设置为可见。

数学

我们得到周长。

double diameter = circumference / 3.14159
double radius = diameter / 2 //Normally done in one step / variable

现在我们必须知道两点之间的距离来比较它。让我们使用map [4] [7]和map [3] [9]。

int x0 = 4;
int y0 = 7;
int x1 = 3;
int y1 = 9;

double distance = Math.sqrt(
        Math.pow(x0 - x1, 2) + 
        Math.pow(y0 - y1, 2)
        );

System.out.println(distance); //2.23606797749979

测试distance > radius

测试每个方格

  • 将上述内容放入方法中:visibleFrom(Square target)
      在比较时,
    • radius应该是一个全局可访问的静态变量。
    • 您的Square对象应该能够移交其坐标。
      • target.getX()
      • target.getY()
  • 可以进行一些优化
    • 只有当它们在广场上时才检查圆形距离。
    • 纯粹沿着xy轴时,不检查任何圆形距离。
    • 找出适合圆圈内部的最大正方形,而不是检查该范围内的圆形距离。
  • 请记住,过早优化和过度优化是一个陷阱。

答案 1 :(得分:0)

我不确切地知道你想要什么,但这里有一些东西可以帮助你。作为警告,这些是未经测试的,但逻辑是合理的。

 //You mentioned circumference, this will find out the circumference but I don't 
 //think you actually need it.
 $circumference_length = 2 * $visibility_range * 3.1415;

 //Plug in the player and target coordinates and how far you can see, this will
 //tell you if the player can see it.  This can be optimized using your object 
 //and player Objects.
 function canSee($player_x, $player_y, $vision_length, $target_x, $target_y){
      $difference_x = $target_x - $player_x;
      $difference_y = $target_y - $player_y;
      $distance = sqrt((pow($difference_x,2) + pow($difference_y, 2));

      if($vision < $distance){
          return false;
      } else {
          return true;
      } 

 }

编辑:为了回应您的澄清,您可以使用上述功能来确定是否应该显示地形对象。

foreach($player as $bot)
{
    foreach($terrain_thing as $terrain)
    {
        //ASSUMING THAT [0] IS ALWAYS X AND [1] IS ALWAYS y, set a third variable
        //to indicate visibility
        $terrain["is_visible"] = canSee($bot[0], $bot[1], $visibility_range, $terrain[0], $terrain[1])


    }
}

答案 2 :(得分:0)

这样的函数会告诉你地图方块是否可见(使用方块中心的距离作为指标;如果你想以另一种方式定义可见性,你可能会这样做,事情变得复杂得多):

function is_visible($mapX, $mapX, $playerX, $playerY, $r) {
    return sqrt(pow($mapX - $playerX, 2) + pow($mapY - $playerY, 2)) <= $r;
}

您可能不需要存储这些值,因为您可以根据需要轻松计算它们。

答案 3 :(得分:0)

我认为Bresenham的圆绘制算法正是您所需要的。