プレイヤーに対して有効な直線でポイントのみをマークすることが重要な場合、次のようなアルゴリズムを使用できます(c ++コード)、通常よりも多くのフラッドフィルを消費します。私は自分でコードをテストしなかったので、あなたはアイデアを得るので、いくつかのマイナーなバグがあるかもしれません(誰かがそれらを修正してくれれば嬉しいです)。
void straightlineFill(Point startPoint, Texture target)
{
queue<Point> pointQueue;
for (int dx = -1;dx <=1;dx ++)
for(int dy = -1;dy <=1;dy++)
if(dx != 0 && dy != 0)
pointQueue.push(point(startPoint.x + dx, startPoint.y + dy));
while (!pointQueue.empty())
{
point front = pointQueue.front();
pointQueue.pop();
if (target.pixelAt(front) == COLOR_SPAWNABLE||
target.pixelAt(front) == COLOR_WALL||
target.pixelAt(front) == COLOR_NOT_SPAWNABLE)
continue;
taraget.setPixelAt(front, colorFilled);
for (int dx = -1;dx <=1;dx ++)
for(int dy = -1;dy <=1;dy++)
if(dx != 0 && dy != 0)
pointQueue.push(point(front.x + dx, front.y + dy));
// up until now was the normal floodfill code
// and here is the part that will do the real straight line checking
// lineDX & lineDY will keep how much the line we are checking is skewed
int lineDX = front.x - startPoint.x;
int lineDY = front.y - startPoint.y;
// step will show us how much we have to travel to reach each point of line
point step;
if (abs(lineDX) < abs(lineDY))
{
if (lineDX < 0)
step = point(-1,0);
if (lineDX == 0)
if (lineDY < 0)
step = point(0,-1);
else
step = point(0,1);
if (lineDX > 0)
step = point(1,0);
}
if (abs(lineDX) < abs(lineDY))
{
if (lineDY < 0)
step = point(0,-1);
if (lineDY == 0)
if (lineDX < 0)
step = point(-1,0);
else
step = point(1,0);
if (lineDY > 0)
step = point(0,1);
}
// moved will keep how much we have traveled so far, it's just some value that will speed up calculations and doesn't have any mathematical value
point moved = 0;
// spawnable will keep if the current pixel is a valid spawnpaint
bool spawnable = true;
// now we will travel on the straight line from player position to the edges of the map and check if whole line is valid spawn points or not.
while (target.isInside(front))
{
front = front + step;
moved = moved + point(step.x * lineDX, step.y * lineDY);
if (step.x != 0 && moved.x < moved.y)
{
moved.x = moved.x - lineDY * sign(lineDY);
front.y = front.y + sign(lineDY);
}
if (step.y != 0 && moved.y < moved.x)
{
moved.y = moved.y - lineDX * sign(lineDX);
front.x = front.x + sign(lineDX);
}
if (target.getPixelAt(front) == COLOR_WALL)
spawnable = false;
if (spawnable)
{
target.setPixelAt(front,COLOR_SPAWNABLE);
for (int dx = -1;dx <=1;dx ++)
for(int dy = -1;dy <=1;dy++)
if(dx != 0 && dy != 0)
pointQueue.push(point(front.x + dx, front.y + dy));
}
else
{
target.setPixelAt(front,COLOR_NOT_SPAWNABLE);
}
}
}
}