我有一个矩形地图,存储为多维数组(即$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,橙色圆圈是玩家,棕色方块是可见的。
答案 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()
x
或y
轴时,不检查任何圆形距离。答案 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的圆绘制算法正是您所需要的。