package byow.Core; import byow.TileEngine.TETile; import byow.TileEngine.Tileset; import java.util.Iterator; import java.util.LinkedList; import java.util.Random; public class Rectangle { static LinkedList hallways = new LinkedList<>(); static LinkedList rectangles = new LinkedList<>(); Rectangle rectangleOne; Rectangle rectangleTwo; Room rectangle; Room room; public static final int MIN_SIZE = 6; public static final int MAX_SIZE = 10; public static final int MAP_WIDTH = 100; public static final int MAP_HEIGHT = 50; public Rectangle(Room room) { this.rectangle = room; } public Room getRoom() { if (this.isFinalRectangle()) { return this.room; } if (this.rectangleOne != null) { Room roomOne = this.rectangleOne.getRoom(); if (roomOne.x != -1) { return roomOne; } } if (this.rectangleTwo != null) { Room roomTwo = this.rectangleTwo.getRoom(); if (roomTwo.x != -1) { return roomTwo; } } return new Room(-1, -1, 0, 0); } public static void createHallway(Random random, Rectangle one, Rectangle two) { Room first = one.getRoom(); Room second = two.getRoom(); int oneX = RandomUtils.uniform(random, first.x, first.x + first.width - 1); int oneY = RandomUtils.uniform(random, first.y, first.y + first.height - 1); int twoX = RandomUtils.uniform(random, second.x, second.x + second.width - 1); int twoY = RandomUtils.uniform(random, second.y, second.y + second.height - 1); int width = oneX - twoX; int height = oneY - twoY; if (width != 0) { if (random.nextBoolean()) { hallways.addLast(new Room(oneX, oneY, Math.abs(width) + 1, 1)); if (height < 0) { hallways.addLast(new Room(twoX, oneY, 1, Math.abs(height))); } else { hallways.addLast(new Room(twoX, oneY, 1, -(Math.abs(height)))); } } else { if (height < 0) { hallways.addLast(new Room(oneX, oneY, 1, Math.abs(height))); } else { hallways.addLast(new Room(oneX, twoY, 1, Math.abs(height))); } hallways.addLast(new Room(oneX, twoY, Math.abs(width) + 1, 1)); } } else { if (height < 0) { hallways.addLast(new Room(oneX, oneY, 1, Math.abs(height))); } else { hallways.addLast(new Room(twoX, twoY, 1, Math.abs(height))); } } } public static void makeHallwayTiles(Rectangle rectangle, TETile[][] world) { if (rectangle == null) { return; } makeHallwayTiles(rectangle.rectangleOne, world); makeHallwayTiles(rectangle.rectangleTwo, world); Iterator allHallways = rectangle.hallways.iterator(); while (allHallways.hasNext()) { Room hallway = allHallways.next(); for (int i = hallway.x; i < hallway.x + hallway.width; i++) { for (int j = hallway.y; j < hallway.y + hallway.height; j++) { if (i > MAP_WIDTH - 5 || j > MAP_HEIGHT - 5) { break; } else { world[i][j] = Tileset.FLOOR; } } } } } public boolean isFinalRectangle() { return this.rectangleOne == null && this.rectangleTwo == null; } public boolean splitRectangle(Random random) { if (!this.isFinalRectangle()) { return false; } if (!rectangle.ableToSplit(this.rectangle.width, this.rectangle.height)) { return false; } boolean direction = getSplitDirection(random, this.rectangle.width, this.rectangle.height); int split; if (direction) { split = RandomUtils.uniform(random, MIN_SIZE, this.rectangle.height - MIN_SIZE + 1); this.rectangleOne = new Rectangle(new Room(this.rectangle.x, this.rectangle.y, this.rectangle.width, split)); this.rectangleTwo = new Rectangle(new Room(this.rectangle.x, this.rectangle.y + split, this.rectangle.width, this.rectangle.height - split)); } else { split = RandomUtils.uniform(random, MIN_SIZE, this.rectangle.width - MIN_SIZE + 1); this.rectangleOne = new Rectangle(new Room(this.rectangle.x, this.rectangle.y, split, this.rectangle.height)); this.rectangleTwo = new Rectangle(new Room(this.rectangle.x + split, this.rectangle.y, this.rectangle.width - split, this.rectangle.height)); } this.rectangles.addLast(this.rectangleOne); this.rectangles.addLast(this.rectangleTwo); return true; } public boolean getSplitDirection(Random random, int width, int height) { if (width / height >= 1.1) { return false; } else if (height / width >= 1.1) { return true; } else { return random.nextBoolean(); } } public static void createBSP(Random random, Rectangle rectangle) { if (rectangle.isFinalRectangle()) { if (rectangle.rectangle.width > MAX_SIZE || rectangle.rectangle.height > MAX_SIZE) { if (rectangle.splitRectangle(random)) { createBSP(random, rectangle.rectangleOne); createBSP(random, rectangle.rectangleTwo); } } } } public static TETile[][] initialize(String seed) { Random random = Helpers.seedToRandom(seed); Rectangle startingRectangle = new Rectangle(new Room(1, 1, MAP_WIDTH - 5, MAP_HEIGHT - 5)); createBSP(random, startingRectangle); startingRectangle.makeRoom(random); //universe.initialize(MAP_WIDTH, MAP_HEIGHT); TETile[][] world = new TETile[MAP_WIDTH][MAP_HEIGHT]; for (int x = 0; x < MAP_WIDTH; x += 1) { for (int y = 0; y < MAP_HEIGHT; y += 1) { world[x][y] = Tileset.NOTHING; } } makeRoomTiles(startingRectangle, world); makeHallwayTiles(startingRectangle, world); makeWalls(world); addAvatar(world); return world; } public static void addAvatar(TETile[][] world) { for (int i = 0; i < MAP_WIDTH; i++) { for (int j = 0; j < MAP_HEIGHT; j++) { if (world[i][j] == Tileset.FLOOR) { world[i][j] = Tileset.AVATAR; return; } } } } public void makeRoom(Random random) { if (this.rectangleOne != null) { this.rectangleOne.makeRoom(random); } if (this.rectangleTwo != null) { this.rectangleTwo.makeRoom(random); } if (this.rectangleOne != null && this.rectangleTwo != null) { createHallway(random, this.rectangleOne, this.rectangleTwo); } if (this.isFinalRectangle()) { int width = RandomUtils.uniform(random, this.rectangle.width / 2, this.rectangle.width - 1); int height = RandomUtils.uniform(random, this.rectangle.height / 2, this.rectangle.height - 1); int x = RandomUtils.uniform(random, 1, this.rectangle.width - width); int y = RandomUtils.uniform(random, 1, this.rectangle.height - height); this.room = new Room(this.rectangle.x + x, this.rectangle.y + y, width, height); } } public static void makeWalls(TETile[][] world) { for (int i = 1; i < MAP_WIDTH - 1; i++) { for (int j = 1; j < MAP_HEIGHT - 1; j++) { if (world[i][j] == Tileset.NOTHING) { if (world[i + 1][j + 1] == Tileset.FLOOR || world[i][j + 1] == Tileset.FLOOR || world[i - 1][j + 1] == Tileset.FLOOR || world[i - 1][j] == Tileset.FLOOR || world[i - 1][j - 1] == Tileset.FLOOR || world[i][j - 1] == Tileset.FLOOR || world[i + 1][j - 1] == Tileset.FLOOR || world[i + 1][j] == Tileset.FLOOR) { world[i][j] = Tileset.WALL; } } } } for (int i = 1; i < MAP_WIDTH - 1; i++) { for (int j = 1; j < MAP_HEIGHT - 1; j++) { if (world[i][j] == Tileset.WALL) { if (world[i][j + 1] == Tileset.FLOOR && world[i][j - 1] == Tileset.FLOOR || world[i - 1][j] == Tileset.FLOOR && world[i + 1][j] == Tileset.FLOOR) { world[i][j] = Tileset.FLOOR; } } } } } public static void makeRoomTiles(Rectangle rectangle, TETile[][] world) { if (rectangle == null) { return; } if (rectangle.isFinalRectangle()) { for (int i = rectangle.room.x; i < rectangle.room.x + rectangle.room.width; i++) { for (int j = rectangle.room.y; j < rectangle.room.y + rectangle.room.height; j++) { world[i][j] = Tileset.FLOOR; } } for (int i = rectangle.room.x; i <= rectangle.room.x + rectangle.room.width; i++) { world[i][rectangle.room.y] = Tileset.WALL; world[i][rectangle.room.y + rectangle.room.height] = Tileset.WALL; } for (int j = rectangle.room.y; j <= rectangle.room.y + rectangle.room.height; j++) { world[rectangle.room.x][j] = Tileset.WALL; world[rectangle.room.x + rectangle.room.width][j] = Tileset.WALL; } } else { makeRoomTiles(rectangle.rectangleOne, world); makeRoomTiles(rectangle.rectangleTwo, world); } } }