计算半径中的二维坐标(对于基于瓦片的游戏)



我已经搜索了一段时间,但没有找到任何令人满意的答案。

目前,我有一个瓦片列表(一个表示瓦片id的int数组)、宽度和高度(以瓦片为单位)。当我渲染它时,所有的瓷砖都被正确放置,等等。但我真正的问题是,我无法找到一种算法来从内到外计算给定半径内(相对于另一个瓷砖)的瓷砖。我计划将其用于照明计算。这就是为什么我需要从内到外(对于梯度)进行计算。我不能在x和y上使用+和-进行静态计算,因为我计划使用可变半径大小。有人知道这样做的好方法吗?

编辑:我所说的"由内而外"是指照明的布置方式,靠近光源的照明应该比远离光源的照明更强烈

0  0  0  0  0  0  0
0  0 --------- 0  0
0  |  *  +  *  |  0
0  |  +  x  +  |  0
0  |  *  +  *  |  0
0  0 --------- 0  0
0  0  0  0  0  0  0

提前感谢:)

关于如何实现这一点的细节,肯定有很多不同的选项。您没有确切地说明如何表示您的"瓦片"(例如,关于接口)。但这里有一种方法,也许它已经有帮助了:

其想法是将瓦片的坐标存储为Point对象的列表。(将这些点转换为1D索引是可能的,但应该与实际问题相当独立)。

这些点是通过沿着有问题的区域的"边缘"行走来计算的:

  • 从右下角开始,向上(dx=0, dy=-1)
  • 从右上角开始,向左(dx=-1, dy=0)
  • 从左上角开始,向下(dx=0, dy=1)
  • 从左下角开始,向右(dx=1, dy=0)

所有这些点都被放入一个列表中,然后该列表按逆时针顺序包含到中心点有一定曼哈顿距离的所有点。

import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
public class TileDistances
{
public static void main(String[] args)
{
int sizeX = 11;
int sizeY = 11;
int centerX = 5;
int centerY = 5;
for (int radius=1; radius<5; radius++)
{
System.out.println(
"Radius "+radius+" around "+centerX+","+centerY);
List<Point> points = coordinates(centerX, centerY, radius);
char c = (char)('0'+radius);
System.out.println(createString(points, sizeX, sizeY, c));
}
}
private static String createString(
List<Point> points, int sizeX, int sizeY, char c)
{
StringBuffer sb = new StringBuffer();
for (int y=0; y<sizeY; y++)
{
for (int x=0; x<sizeX; x++)
{
Point p = new Point(x,y);
if (points.contains(p))
{
sb.append(c);
}
else
{
sb.append(".");
}
}
sb.append("n");
}
return sb.toString();
}
private static List<Point> coordinates(
int cx, int cy, int r)
{
List<Point> coordinates = new ArrayList<Point>();
int steps = r + r;
addAll(cx + r, cy + r,  0, -1, steps, coordinates);
addAll(cx + r, cy - r, -1,  0, steps, coordinates);
addAll(cx - r, cy - r,  0,  1, steps, coordinates);
addAll(cx - r, cy + r,  1,  0, steps, coordinates);
return coordinates;
}
private static void addAll(
int x0, int y0, int dx, int dy, int steps,
List<Point> coordinates)
{
int x = x0;
int y = y0;
for (int i=0; i<steps; i++)
{
coordinates.add(new Point(x,y));
x += dx;
y += dy;
}
}
}

在本例中,将打印半径1至4,例如:

Radius 3 around 5,5
...........
...........
..3333333..
..3.....3..
..3.....3..
..3.....3..
..3.....3..
..3.....3..
..3333333..
...........
...........

(根据瓦片的具体表示方式,可能会有更高效和/或更优雅的解决方案,但我认为这一解决方案很容易理解,而且通用,因为它只提供了一组坐标,而不会对底层数据结构进行假设)。

最新更新