From 0ff9af6522e34ce24efdef789440ed7397ff0717 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Sun, 28 May 2017 14:06:40 -0400 Subject: [PATCH] v0.6.0: refactoring, bugfixes, and improvements to builder logic --- .../levels/builders/Builder.java | 105 ++++++++++-------- .../levels/builders/LoopBuilder.java | 21 +++- .../levels/builders/RegularBuilder.java | 6 +- 3 files changed, 76 insertions(+), 56 deletions(-) diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/Builder.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/Builder.java index 9f63a69c4..2486f2328 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/Builder.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/Builder.java @@ -68,61 +68,67 @@ public abstract class Builder { } } - //iterate through all rooms we are overlapping, and find which one would take - //the largest area reduction to resolve the overlapping - Room biggestCollision = null; - int wDiff, hDiff, biggestDiff = 0; - boolean widthCollision = false; - for (Room room : colliding){ + //iterate through all rooms we are overlapping, and find the closest one + Room closestRoom = null; + int closestDiff = Integer.MAX_VALUE; + boolean inside = true; + int curDiff = 0; + for (Room curRoom : colliding){ + + if (start.x <= curRoom.left){ + inside = false; + curDiff += curRoom.left - start.x; + } else if (start.x >= curRoom.right){ + inside = false; + curDiff += start.x - curRoom.right; + } + + if (start.y <= curRoom.top){ + inside = false; + curDiff += curRoom.top - start.y; + } else if (start.y >= curRoom.bottom){ + inside = false; + curDiff += start.y - curRoom.bottom; + } + + if (inside){ + space.set(start.x, start.y, start.x, start.y); + return space; + } + + if (curDiff < closestDiff){ + closestDiff = curDiff; + closestRoom = curRoom; + } + + } + + int wDiff, hDiff; + if (closestRoom != null){ + wDiff = Integer.MAX_VALUE; - if (room.left >= start.x){ - wDiff = (space.right - room.left) * (space.height() + 1); - } else if (room.right <= start.x){ - wDiff = (room.right - space.left) * (space.height() + 1); + if (closestRoom.left >= start.x){ + wDiff = (space.right - closestRoom.left) * (space.height() + 1); + } else if (closestRoom.right <= start.x){ + wDiff = (closestRoom.right - space.left) * (space.height() + 1); } hDiff = Integer.MAX_VALUE; - if (room.top >= start.y){ - hDiff = (space.bottom - room.top) * (space.width() + 1); - } else if (room.bottom <= start.y){ - hDiff = (room.bottom - space.top) * (space.width() + 1); + if (closestRoom.top >= start.y){ + hDiff = (space.bottom - closestRoom.top) * (space.width() + 1); + } else if (closestRoom.bottom <= start.y){ + hDiff = (closestRoom.bottom - space.top) * (space.width() + 1); } - //our start is inside this room, return an empty rect - if (hDiff == Integer.MAX_VALUE && wDiff == Integer.MAX_VALUE){ - space.set(0, 0, 0, 0); - return space; - + //reduce by as little as possible to resolve the collision + if (wDiff < hDiff || wDiff == hDiff && Random.Int(2) == 0){ + if (closestRoom.left >= start.x && closestRoom.left < space.right) space.right = closestRoom.left; + if (closestRoom.right <= start.x && closestRoom.right > space.left) space.left = closestRoom.right; } else { - if (wDiff < hDiff || (wDiff == hDiff && Random.Int(2) == 0)){ - if (wDiff >= biggestDiff){ - biggestDiff = wDiff; - biggestCollision = room; - widthCollision = true; - } - - } else { - if (hDiff >= biggestDiff){ - biggestDiff = hDiff; - biggestCollision = room; - widthCollision = false; - } - } - + if (closestRoom.top >= start.y && closestRoom.top < space.bottom) space.bottom = closestRoom.top; + if (closestRoom.bottom <= start.y && closestRoom.bottom > space.top) space.top = closestRoom.bottom; } - - } - - //reduce the available space in order to not overlap with the biggest collision we found - if (biggestCollision != null){ - if (widthCollision){ - if (biggestCollision.left >= start.x && biggestCollision.left < space.right) space.right = biggestCollision.left; - if (biggestCollision.right <= start.x && biggestCollision.right > space.left) space.left = biggestCollision.right; - } else { - if (biggestCollision.top >= start.y && biggestCollision.top < space.bottom) space.bottom = biggestCollision.top; - if (biggestCollision.bottom <= start.y && biggestCollision.bottom > space.top) space.top = biggestCollision.bottom; - } - colliding.remove(biggestCollision); + colliding.remove(closestRoom); } else { colliding.clear(); } @@ -140,7 +146,10 @@ public abstract class Builder { PointF fromCenter = new PointF((from.left + from.right)/2f, (from.top + from.bottom)/2f); PointF toCenter = new PointF((to.left + to.right)/2f, (to.top + to.bottom)/2f); double m = (toCenter.y - fromCenter.y)/(toCenter.x - fromCenter.x); - return (float)(A*(Math.atan(m) + Math.PI/2f)); + + float angle = (float)(A*(Math.atan(m) + Math.PI/2.0)); + if (fromCenter.x > toCenter.x) angle -= 180f; + return angle; } //Attempts to place a room such that the angle between the center of the previous room diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/LoopBuilder.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/LoopBuilder.java index 3745c3429..86a71a1eb 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/LoopBuilder.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/LoopBuilder.java @@ -97,7 +97,7 @@ public class LoopBuilder extends RegularBuilder { } } - if (exit != null) loop.add(loop.size()/2, exit); + if (exit != null) loop.add((loop.size()+1)/2, exit); Room prev = entrance; float targetAngle; @@ -114,16 +114,27 @@ public class LoopBuilder extends RegularBuilder { } } - //FIXME this is lazy, there are ways to do this without relying on chance - if (!prev.connect(entrance)){ - return null; + //FIXME this is still fairly chance reliant + // should just write a general function for stitching two rooms together in builder + while (!prev.connect(entrance)){ + + ConnectionRoom c = ConnectionRoom.createRoom(); + if (placeRoom(loop, prev, c, angleBetweenRooms(prev, entrance)) == -1){ + return null; + } + loop.add(c); + rooms.add(c); + prev = c; } if (shop != null) { float angle; + int tries = 10; do { angle = placeRoom(loop, entrance, shop, Random.Float(360f)); - } while (angle == -1); + tries--; + } while (angle == -1 && tries >= 0); + if (angle == -1) return null; } ArrayList branchable = new ArrayList<>(loop); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/RegularBuilder.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/RegularBuilder.java index 9508dd686..9eb33e8df 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/RegularBuilder.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/RegularBuilder.java @@ -56,8 +56,8 @@ public abstract class RegularBuilder extends Builder { return this; } - protected float[] pathTunnelChances = new float[]{2, 3, 1}; - protected float[] branchTunnelChances = new float[]{3, 2, 1}; + protected float[] pathTunnelChances = new float[]{2, 6, 2}; + protected float[] branchTunnelChances = new float[]{5, 4, 1}; public RegularBuilder setTunnelLength( float[] path, float[] branch){ pathTunnelChances = path; @@ -173,7 +173,7 @@ public abstract class RegularBuilder extends Builder { continue; } - branchable.addAll(connectingRoomsThisBranch); + if (Random.Float() < 0.33f) branchable.addAll(connectingRoomsThisBranch); if (r.maxConnections(Room.ALL) > 1) { if (r instanceof StandardRoom){ for (int j = 0; j < ((StandardRoom) r).sizeCat.connectionWeight(); j++){