【问题标题】:Calculate 2d coordinates in radius (for a tile based game)计算半径中的 2d 坐标(对于基于图块的游戏)
【发布时间】:2015-04-27 01:55:45
【问题描述】:

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

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

编辑:“从内到外”我的意思是照明的布置方式,靠近光源的照明应该比远离它的地方更强烈。我打算用下面的 ASCII 东西直观地展示它:

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

提前致谢:)

【问题讨论】:

  • 您可能应该详细说明这个“由内而外”部分的含义(因为这似乎很重要)。您需要按特定顺序排列的瓷砖吗? (就像一个“螺旋”向外走?)还是只需要“距离为 1 的所有字段,然后是距离为 2 的所有字段,......”等等?
  • @Marco13 确实,为了计算亮度,顺序很重要(或者至少是到光源的距离),例如瓷砖的阿尔法。
  • 我看,不过从图片上看不清楚你是在找中心点的en.wikipedia.org/wiki/Von_Neumann_neighborhood还是en.wikipedia.org/wiki/Moore_neighborhood。
  • @Marco13 抱歉,我认为这更像是摩尔社区。感谢您的链接顺便说一句

标签: java 2d


【解决方案1】:

关于如何实施的细节当然有很多不同的选择。您没有确切说明您如何表示您的“图块”(例如,关于界面)。但这是一种方法,也许它已经有所帮助:

这个想法是将图块的坐标存储为Point 对象的列表。 (将这些点转换为一维索引是可能的,但应该完全独立于实际问题)。

这些点是通过沿着相关区域的“边缘”行走计算得出的:

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

所有这些点都被放入一个列表中,然后按逆时针顺序包含与中心点有一定Manhattan Distance的所有点。

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..
...........
...........

(可能有更有效和/或更优雅的解决方案,具体取决于瓷砖的精确表示方式,但我认为这个很容易理解并且一般适用,因为它只是提供一组坐标,并且不对底层数据结构做出假设)。

【讨论】:

    猜你喜欢
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 2020-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多