Java RogueLike视线问题

时间:2014-05-01 00:22:28

标签: java roguelike

我正在制作一个roguelike游戏,我正试图在我的游戏中实现“Quick and Dirty”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;
}

1 个答案:

答案 0 :(得分:4)

首先,我注意到函数中有一些奇怪的东西。你实际上有三组坐标 - (xx,yy),(xx2,yy2)和(player.x,player.y)。据我所知,算法是从A点到B点画一条线,然后看看沿线的任何一块是否阻挡了访问。为此,你只需要两组坐标,所以也许你的错误就像用(xx,yy)替换(player.x,player.y)一样简单。

其次,在roguelike中,您通常使用基于图块的环境,其中不需要三角法,甚至认为是浪费。由于你的所有tile都有整数位置,所以你绝对应该能够为像这样的关键的低级实现提供一个仅整数的实现。

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

如果你想更快地测试你的,那我就从Github中删除了我的 roguelike的实现。您必须更改它,但是当然您还要代表地图,并且可能会删除阻止检查。

/**
 * 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(MinathMap 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的线描算法,这是roguelikes中视线计算的常用方法。为了我自己的目的,我也沿着线返回点(然后你可以用它来标记那些坐标 - 例如使用额外的光照参数)。这些信息很有价值,在你经历了所有麻烦之后不应该被扔掉,以找出瓷砖是否完全可见!