Java中的矩形重叠

时间:2018-11-13 23:40:24

标签: java procedural-generation roguelike

我正在尝试制作一个随机地图生成器。它应在随机坐标处创建一个随机大小的房间,并删除与其他房间重叠的房间。但是,重叠检查不起作用。这是代码的相关部分:

public static void generateMap() {
    rooms[0] = new Room(0,10,10,5); // For some reason doesn't work without this?
    for (int i=0;i<ROOMS;i++) {
        int x = randomWithRange(0,WIDTH);
        int y = randomWithRange(0,HEIGHT);
        int height = randomWithRange(MINROOMSIZE,MAXROOMSIZE);
        int width = randomWithRange(MINROOMSIZE,MAXROOMSIZE);
        while (x+width > WIDTH) {
            x--;
        }
        while (y+height > HEIGHT) {
            y--;
        }
        Room room = new Room(x,y,width,height);
        if (room.overlaps(rooms) == false) {
            rooms[i] = room;
        }

    }
}

然后是Room类:

import java.awt.*;

public class Room {
    int x;
    int y;
    int height;
    int width;

public Room(int rx, int ry, int rwidth, int rheight) {
    x = rx;
    y = ry;
    height = rheight;
    width = rwidth;
}
boolean overlaps(Room[] roomlist) {
    boolean overlap = true;
    Rectangle r1 = new Rectangle(x,y,width,height);
    if (roomlist != null) {
        for (int i=0;i<roomlist.length;i++) {
            if (roomlist[i] != null) {
                Rectangle r2 = new Rectangle(roomlist[i].x,roomlist[i].y,roomlist[i].width,roomlist[i].height);
                if (!r2.intersects(r1) && !r1.intersects(r2)) {
                    overlap = false;
                }
                else {
                    overlap = true;
                }
            }                
        }
    }
    return overlap;
}

}

因此,我一直在进行测试,每次都删除一些房间,但是根据房间的数量,总有一些房间是重叠的。肯定有一些我现在看不到的愚蠢简单解决方案...而且,为什么除非我手动添加第一个房间,否则它不生成任何房间?谢谢

2 个答案:

答案 0 :(得分:1)

您的问题是overlaps函数的这一部分:

overlap = false;

您的代码中正在发生的事情是,您不断检查房间是否重叠,但是如果您发现一个重叠的房间,您就会继续前进。然后,当您找到重叠的房间时,请重置该标志。实际上,该代码等效于仅检查最后一个房间。

完全删除重叠标志。不用overlap = true;语句,而放return true;(因为在这一点上我们知道至少一个房间是重叠的)。当发现房间与其他房间没有重叠时(在for循环中),不要执行任何操作。最后,在for循环之后,return false;实际上已经执行了代码,这意味着没有重叠的空间(否则它将已经返回)

注意:我相信条件!r2.intersects(r1) && !r1.intersects(r2)是多余的。 .intersects(r)应该是可交换的,这意味着r1.intersects(r2)r2.intersects(r1)给出相同的结果。

答案 1 :(得分:0)

对于第一个已初始化第一个房间的问题,您不必这样做。

rooms[0] = new Room(0,10,10,5); // For some reason doesn't work without this?

您只需要检查第一个房间,而无需检查重叠,因为它是第一个房间。 对于第二个问题,您可以在第一次找到相交时返回true,否则在循环结束时返回false。

代码供您参考。

class Room {
int x;
int y;
int height;
int width;

public Room(int rx, int ry, int rwidth, int rheight) {
    x = rx;
    y = ry;
    height = rheight;
    width = rwidth;
}

boolean overlaps(Room[] roomlist) {
    Rectangle r1 = new Rectangle(x, y, width, height);
    if (roomlist != null) {
        for (int i = 0; i < roomlist.length; i++) {
            if (roomlist[i] != null) {
                Rectangle r2 = new Rectangle(roomlist[i].x, roomlist[i].y, roomlist[i].width, roomlist[i].height);
                if (r2.intersects(r1)) {
                    return true;
                } 
            }
        }
    }
    return false;
}
}

public class RoomGenerator {
private static final int ROOMS = 10;
private static final int WIDTH = 1200;
private static final int HEIGHT = 1000;
private static final int MINROOMSIZE = 10;
private static final int MAXROOMSIZE = 120;

public static void main(String[] args) {
    generateMap();
}

public static void generateMap() {
    Room rooms[] = new Room[10];
    for (int i = 0; i < ROOMS; i++) {
        int x = randomWithRange(0, WIDTH);
        int y = randomWithRange(0, HEIGHT);
        int height = randomWithRange(MINROOMSIZE, MAXROOMSIZE);
        int width = randomWithRange(MINROOMSIZE, MAXROOMSIZE);
        while (x + width > WIDTH) {
            x--;
        }
        while (y + height > HEIGHT) {
            y--;
        }
        Room room = new Room(x, y, width, height);
        if( i ==0)
        {
            rooms[0] = room;
        }else if (room.overlaps(rooms) == false) {
            rooms[i] = room;
        }
    }
}

private static int randomWithRange(int min, int max) {
    // TODO Auto-generated method stub
    Random r = new Random();
    return r.nextInt((max - min) + 1) + min;
}
}