diff --git a/Plugin NPC/src/main/java/net/simon987/npcplugin/VaultWorldGenerator.java b/Plugin NPC/src/main/java/net/simon987/npcplugin/VaultWorldGenerator.java index ae465ed..264961c 100644 --- a/Plugin NPC/src/main/java/net/simon987/npcplugin/VaultWorldGenerator.java +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/VaultWorldGenerator.java @@ -7,20 +7,23 @@ import net.simon987.server.logging.LogManager; import java.awt.*; import java.util.ArrayList; +import java.util.Comparator; +import java.util.Random; public class VaultWorldGenerator { - public World generateVaultWorld(int x, int y, ArrayList openings, String dimension) { + public World generateVaultWorld(int worldX, int worldY, ArrayList openings, String dimension) { LogManager.LOGGER.info("Generating vault World"); /* * Openings are always at the same spot (marked by '?') * 1. Rectangles of random size are generated - * 2. They are connected with tunnels from bottom to top, + * 2. Openings are generated (if another vault world is connected on this direction) + * 3. They are connected with tunnels from bottom to top, * by their roomCenter, alternating between horizontal first * tunnels and vertical first - * 3. Tiles adjacent to floor tiles are set to wall tiles + * 4. Tiles adjacent to floor tiles are set to wall tiles * Example map: * * # # # # # # # - - - # ? ? # - - - - - - - - - - @@ -49,22 +52,75 @@ public class VaultWorldGenerator { * - - - - - - - - - - # ? ? # - - - - - - - - - - */ + Random random = new Random(); + int worldSize = 20; int floorTile = 4; int wallTile = 5; - int minRoomCount = 3; - int maxRoomCount = 6; + int minRoomCount = 5; + int maxRoomCount = 8; int minRoomWidth = 4; int minRoomHeight = 4; int maxRoomWidth = 8; int maxRoomHeight = 8; - ArrayList roomCenters = new ArrayList<>(); + ArrayList roomCenters = new ArrayList<>(maxRoomCount + 4); + ArrayList rooms = new ArrayList<>(maxRoomCount); - World world = new World(x, y, new TileMap(worldSize, worldSize), dimension); + World world = new World(worldX, worldY, new TileMap(worldSize, worldSize), dimension); TileMap map = world.getTileMap(); + //Generate rectangles of random size + int roomCount = random.nextInt(maxRoomCount - minRoomCount) + minRoomCount; + + for (int i = 0; i < roomCount; i++) { + + int roomWidth = random.nextInt(maxRoomWidth - minRoomWidth) + minRoomWidth; + int roomHeight = random.nextInt(maxRoomHeight - minRoomHeight) + minRoomHeight; + + int attempts = 35; + Point roomCorner; + Rectangle room = null; + + //Try to find a spot that doesn't intersect another room + attemptsLoop: + while (true) { + + if (attempts < 0) { + roomCorner = null; + break; + } + + roomCorner = new Point(random.nextInt((worldSize - roomWidth) - 2) + 2, + random.nextInt((worldSize - roomHeight) - 2) + 2); + + room = new Rectangle(roomCorner.x, roomCorner.y, roomWidth, roomHeight); + + for (Rectangle otherRoom : rooms) { + if (otherRoom.intersects(room)) { + attempts--; + continue attemptsLoop; + } + } + + break; + } + + if (roomCorner != null) { + for (int x = roomCorner.x; x < roomCorner.x + roomWidth; x++) { + for (int y = roomCorner.y; y < roomCorner.y + roomHeight; y++) { + map.setTileAt(floorTile, x, y); + } + } + + rooms.add(room); + roomCenters.add(new Point(roomCorner.x + roomWidth / 2, roomCorner.y + roomHeight / 2)); + } else { + break; + } + } + //Create openings for (Direction opening : openings) { switch (opening) { @@ -82,7 +138,7 @@ public class VaultWorldGenerator { map.setTileAt(floorTile, worldSize - 1, worldSize / 2 - 1); map.setTileAt(floorTile, worldSize - 2, worldSize / 2); map.setTileAt(floorTile, worldSize - 2, worldSize / 2 - 1); - roomCenters.add(new Point(worldSize - 1, worldSize / 2 - 1)); + roomCenters.add(new Point(worldSize - 2, worldSize / 2 - 1)); break; case SOUTH: @@ -98,15 +154,111 @@ public class VaultWorldGenerator { map.setTileAt(floorTile, 0, worldSize / 2 - 1); map.setTileAt(floorTile, 1, worldSize / 2); map.setTileAt(floorTile, 1, worldSize / 2 - 1); - roomCenters.add(new Point(0, worldSize / 2 - 1)); + roomCenters.add(new Point(1, worldSize / 2 - 1)); break; } } - //Generate rectangles of random size + LogManager.LOGGER.severe(world.toString()); + + //Connect rooms together, from bottom to top + roomCenters.sort(new RoomCenterComparator()); + boolean xFirst = true; //Start the tunnel horizontally + + for (int i = 0; i < roomCenters.size() - 1; i++) { + //Note to self: I wouldn't bother trying to understand what's in this for loop, + //If this needs to be modified just trash it and start over + + if (xFirst) { + if (roomCenters.get(i + 1).x - roomCenters.get(i).x < 0) { + for (int x = roomCenters.get(i).x; x > roomCenters.get(i + 1).x; x--) { + map.setTileAt(floorTile, x, roomCenters.get(i).y); + } + } else { + for (int x = roomCenters.get(i).x; x < roomCenters.get(i + 1).x; x++) { + map.setTileAt(floorTile, x, roomCenters.get(i).y); + } + } + + if (roomCenters.get(i + 1).y - roomCenters.get(i).y < 0) { + for (int y = roomCenters.get(i).y; y > roomCenters.get(i + 1).y; y--) { + map.setTileAt(floorTile, roomCenters.get(i + 1).x, y); + } + } else { + for (int y = roomCenters.get(i).y; y < roomCenters.get(i + 1).y; y++) { + map.setTileAt(floorTile, roomCenters.get(i + 1).x, y); + } + } + } else { + + if (roomCenters.get(i + 1).x - roomCenters.get(i).x < 0) { + for (int x = roomCenters.get(i).x; x > roomCenters.get(i + 1).x; x--) { + map.setTileAt(floorTile, x, roomCenters.get(i + 1).y); + } + } else { + for (int x = roomCenters.get(i).x; x < roomCenters.get(i + 1).x; x++) { + map.setTileAt(floorTile, x, roomCenters.get(i + 1).y); + } + } + + if (roomCenters.get(i + 1).y - roomCenters.get(i).y < 0) { + for (int y = roomCenters.get(i).y; y > roomCenters.get(i + 1).y; y--) { + map.setTileAt(floorTile, roomCenters.get(i).x, y); + } + } else { + for (int y = roomCenters.get(i).y; y < roomCenters.get(i + 1).y; y++) { + map.setTileAt(floorTile, roomCenters.get(i).x, y); + } + } + } + + xFirst = !xFirst; + } + + //Tiles adjacent to floor tiles are set to wall tiles + for (int x = 0; x < worldSize; x++) { + for (int y = 0; y < worldSize; y++) { + + if (map.getTileAt(x, y) != floorTile && hasTileAdjacent(x, y, map, floorTile)) { + map.setTileAt(wallTile, x, y); + } + } + } + + //Set other tiles to 'void' + for (int x = 0; x < worldSize; x++) { + for (int y = 0; y < worldSize; y++) { + + if (map.getTileAt(x, y) != floorTile && map.getTileAt(x, y) != wallTile) { + map.setTileAt(-1, x, y); + } + } + } return world; } + private boolean hasTileAdjacent(int x, int y, TileMap map, int tile) { + + for (int dX = -1; dX <= 1; dX++) { + for (int dY = -1; dY <= 1; dY++) { + + if (map.getTileAt(x + dX, y + dY) == tile) { + return true; + } + } + } + + return false; + } + + private class RoomCenterComparator implements Comparator { + @Override + public int compare(Point o1, Point o2) { + return o1.y - o2.y; + } + } + + }