首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java RogueLike视线问题

Java RogueLike视线问题
EN

Stack Overflow用户
提问于 2014-05-01 00:22:27
回答 1查看 838关注 0票数 2

我正在做一个流氓游戏,我试图在我的游戏中实现“快速和肮脏”的FOV技术,但我有一些问题。我几乎可以肯定,它是在我的函数中完成的,在这个函数中,我有一个x和y变量,沿着两个点之间的一个角度移动(我正在检查的瓷砖和玩家)。

如果您不知道什么是“快速和脏”的FOV,这里是链接FOV/LOS

代码

代码语言:javascript
复制
  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;
}
EN

回答 1

Stack Overflow用户

发布于 2014-05-01 01:44:01

首先,我注意到功能中有一些奇怪的东西。实际上,您有三组坐标- (xx,yy),(xx2,yy2)和(player.x,player.y)。据我所知,算法是从A点画一条线到B点,然后看看沿着这条线的瓷砖是否阻塞了访问。为此,您只需要两组坐标,所以您的bug可能就像用(xx,yy)替换(player.x,player.y)一样简单。

其次,在类似罗格利埃的环境中,通常是基于瓷砖的环境,在这些环境中,三角学是不必要的,甚至被认为是浪费的。因为您的所有瓷砖都有整数位置,所以您肯定能够为这样一个关键的、低级别的实现执行一个仅为整数的实现。

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

如果您想要更快地测试您的Github,我就把我的roguelike的实现从Github中提取出来。当然,您必须更改它,因为您表示的是映射,并且有可能删除阻塞检查。

代码语言:javascript
复制
/**
 * 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的直线绘制算法,这是在roguelikes中进行视线线计算的一种常见方法.我还返回沿线的点,以我自己的目的(然后您可以使用它来标记这些坐标-例如附加的照明参数)。这个信息是有价值的,不应该被扔掉后,你经历了所有的麻烦,如果瓷砖是可见的!

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23400272

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档