【问题标题】:Java RogueLike line of sight issueJava RogueLike 视线问题
【发布时间】:2014-05-01 00:22:27
【问题描述】:

我正在制作一款 roguelike 游戏,并尝试在我的游戏中实施“快速而肮脏”的 FOV 技术,但我遇到了一些问题。我几乎可以肯定它是在我的函数中完成线计算的,其中我有一个 x 和 y 变量沿着 2 个点(我正在检查的图块和玩家)之间的角度移动。

如果你不知道什么是“又快又脏”的 FOV,这里是链接http://www.roguebasin.com/index.php?title=Quick_and_dirty_FOV/LOS

代码

  public static boolean lineOfSight( int xx, int yy, int xx2, int yy2) {
    float deltaX = xx - xx2;
    float deltaY = yy - yy2;
    float angle = (float) Math.atan2(deltaY,deltaX);
    int distance = distanceCheck(player.x,player.y,xx2,yy2);
    int counter = 0;
    while(counter < distance) {
        counter ++;
        xx += (int) (Math.sin(angle));
        yy += (int) (Math.cos(angle));
        if(map[xx][yy] == 1) {
            return false;
        } 
    }
    return true;
}

【问题讨论】:

  • 您的预期产出与实际产出是什么?
  • 你到底是什么意思?
  • 当您测试您的方法时,您必须向它传递一些值并期待一些输出。你正在运行什么测试,你得到了什么不正确的输出。
  • 我给它我的玩家 x 和 y 点以及瓷砖 x 和 y 点,并且该区域中的所有内容都可见,或者缺少四分之一的圆圈我最好的选择是我计算我的角度错误。 .im 只是不确定我做错了什么

标签: java roguelike


【解决方案1】:

首先,我注意到函数中有一些奇怪的东西。您实际上有三组坐标 - (xx, yy)、(xx2, yy2) 和 (player.x, player.y)。据我了解,算法是从 A 点到 B 点画一条线,然后查看沿线的任何瓦片是否阻塞了访问。为此,您只需要两组坐标,因此您的错误可能就像将 (player.x, player.y) 替换为 (xx, yy) 一样简单。

其次,在 roguelike 中,你通常会使用基于图块的环境,其中三角函数是不必要的,甚至被认为是浪费的。由于您的所有图块都有整数位置,因此您绝对应该能够为像这样的关键低级实现拉出仅整数实现。

最后,由于您将输入坐标存储为整数,因此当角度的 sin 和 cos 小于 1 时,内部循环将无法按预期工作。具体来说,坐标变量不会存储部分平铺移动。在循环中放置一个 print 语句,看看 (xx, yy) 到底发生了什么。

如果你想更快地测试你的,我将 my roguelike 的实现从 Github 上撤了下来。当然,您必须根据您所代表的地图进行更改,并且可能会删除阻塞检查。

/**
 * Check if the point (x0, y0) can see point (x1, y1) by drawing a line
 * and testing for the "blocking" property at each new tile. Returns the
 * points on the line if it is, in fact, visible. Otherwise, returns an 
 * empty list (rather than null - Efficient Java, item #43).
 * 
 * http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
 */
public static List<Point> isVisible(GameMap map, int x0, int y0, int x1, int y1) {
    List<Point> line = new LinkedList<Point>();
    line.add(new Point(x0, y0));
    int dx = Math.abs(x1 - x0);
    int dy = Math.abs(y1 - y0);
    int sx = (x0 < x1) ? TILE_X : -TILE_X;
    int sy = (y0 < y1) ? TILE_Y : -TILE_Y;
    int err = dx - dy;
    int e2;

    while (!(x0 == x1 && y0 == y1)) {            
        if (map.isBlocked(x0, y0)) {
            line.clear();
            return line;
        }

        e2 = 2 * err;

        if (e2 > -dy) {
            err -= dy;
            x0 += sx;   
        }

        if (e2 < dx) {
            err += dx;
            y0 += sy;
        }

        line.add(new Point(x0, y0));
    }

    return line;
}

代码实现了 Bresenham 的画线算法,这是 roguelike 中视线计算的常用方法。我还为我自己的目的返回沿线的点(然后您可以使用它以某种方式标记这些坐标 - 例如使用额外的照明参数)。这些信息很有价值,不应该在您费尽千辛万苦地找到该图块是否可见后丢弃!

【讨论】:

  • 这是一种常见的 if 表达式语法,在除 Java 之外的许多其他语言中。 result = condition ? when-true : when-false.
  • 啊酷有点糟糕,因为我删除了视图的所有内容并创建了一个新的视图系统,就像原来的 roguelike rogue 一样
  • @Misha 你能发布一个指向你的 GitHub 的链接吗?我喜欢关注人们并查看他们的项目;)
  • @Misha 不是每个人都将他们的统计数据最大化...你有下载链接吗?
  • @AnubianNoob 还不能玩 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-20
相关资源
最近更新 更多