v0.6.0: lots of line builder implementation and general improvements

This commit is contained in:
Evan Debenham 2017-04-05 19:59:02 -04:00
parent f20a5c1dcf
commit 84c405ef2b
5 changed files with 144 additions and 37 deletions

View File

@ -261,14 +261,6 @@ public abstract class Level implements Bundlable {
decorate();
PathFinder.setMapSize(width(), height());
passable = new boolean[length()];
losBlocking = new boolean[length()];
flamable = new boolean[length()];
secret = new boolean[length()];
solid = new boolean[length()];
avoid = new boolean[length()];
water = new boolean[length()];
pit = new boolean[length()];
buildFlagMaps();
cleanWalls();
@ -292,6 +284,17 @@ public abstract class Level implements Bundlable {
visited = new boolean[length];
mapped = new boolean[length];
Dungeon.visible = new boolean[length];
fieldOfView = new boolean[length()];
passable = new boolean[length()];
losBlocking = new boolean[length()];
flamable = new boolean[length()];
secret = new boolean[length()];
solid = new boolean[length()];
avoid = new boolean[length()];
water = new boolean[length()];
pit = new boolean[length()];
}
public void reset() {
@ -315,11 +318,9 @@ public abstract class Level implements Bundlable {
}
if (bundle.contains("width") && bundle.contains("height")){
width = bundle.getInt("width");
height = bundle.getInt("height");
setSize( bundle.getInt("width"), bundle.getInt("height"));
} else
width = height = 32; //default sizes
length = width * height;
setSize( 32, 32); //default sizes
PathFinder.setMapSize(width(), height());
mobs = new HashSet<>();
@ -593,17 +594,6 @@ public abstract class Level implements Bundlable {
}
protected void buildFlagMaps() {
fieldOfView = new boolean[length()];
passable = new boolean[length()];
losBlocking = new boolean[length()];
flamable = new boolean[length()];
secret = new boolean[length()];
solid = new boolean[length()];
avoid = new boolean[length()];
water = new boolean[length()];
pit = new boolean[length()];
for (int i=0; i < length(); i++) {
int flags = Terrain.flags[map[i]];

View File

@ -22,8 +22,12 @@
package com.shatteredpixel.shatteredpixeldungeon.levels.builders;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.watabou.utils.Point;
import com.watabou.utils.Random;
import com.watabou.utils.Rect;
import java.util.ArrayList;
import java.util.Iterator;
public abstract class Builder {
@ -34,4 +38,85 @@ public abstract class Builder {
//returns null on failure
public abstract ArrayList<Room> build(ArrayList<Room> rooms);
protected Rect findFreeSpace(Point start, ArrayList<Room> rooms, int maxSize){
Rect space = new Rect(start.x-maxSize, start.y-maxSize, start.x+maxSize, start.y+maxSize);
ArrayList<Room> colliding = new ArrayList<>(rooms);
do{
//remove any rooms we aren't currently overlapping
Iterator<Room> it = colliding.iterator();
while (it.hasNext()){
Room room = it.next();
//if not colliding
if ( Math.max(space.left, room.left) >= Math.min(space.right, room.right)
|| Math.max(space.top, room.top) >= Math.min(space.bottom, room.bottom) ){
it.remove();
}
}
//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){
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);
}
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);
}
//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;
} 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;
}
}
}
}
//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);
} else {
colliding.clear();
}
//loop until we are no longer colliding with any rooms
} while (!colliding.isEmpty());
return space;
}
}

View File

@ -28,7 +28,9 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EntranceRo
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.ExitRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.tunnel.TunnelRoom;
import com.watabou.utils.Point;
import com.watabou.utils.Random;
import com.watabou.utils.Rect;
import java.util.ArrayList;
@ -73,7 +75,7 @@ public class LineBuilder extends Builder {
shop.connect(entrance);
}
int standardsOnPath = standards.size()/2 + Random.Int(3) - 1;
int standardsOnPath = standards.size()/5 + Random.Int(2);
standardsOnPath = Math.min(standardsOnPath, standards.size());
//standardsOnPath = standards.size();
@ -157,7 +159,7 @@ public class LineBuilder extends Builder {
if (!placeBranchRoom(up, curr, r, rooms)){
continue;
}
if (r instanceof StandardRoom) {
if (r instanceof StandardRoom && Random.Int(3) == 0) {
if (up) upBrancheable.add(r);
else downBrancheable.add(r);
}
@ -169,11 +171,24 @@ public class LineBuilder extends Builder {
}
private boolean placeBranchRoom(boolean up, Room curr, Room next, ArrayList<Room> collision){
next.setSize();
next.setPos( curr.left + (curr.width()-next.width())/2, up ? curr.top - next.height()+1 : curr.bottom);
next.connect(curr);
return true;
Rect space = findFreeSpace(
new Point( curr.left + curr.width()/2, up ? curr.top : curr.bottom),
collision,
Math.max(next.maxWidth(), next.maxHeight()));
if (next.setSizeWithLimit(space.width()+1,space.height()+1 )){
next.setPos( curr.left + (curr.width()-next.width())/2, up ? curr.top - next.height()+1 : curr.bottom);
if (next.right > space.right){
next.shift( space.right - next.right, 0);
} else if (next.left < space.left){
next.shift( space.left - next.left, 0);
}
return next.connect(curr);
} else {
return false;
}
}
}

View File

@ -83,20 +83,36 @@ public class Room extends Rect implements Graph.Node, Bundlable {
return setSize(minWidth(), maxWidth(), minHeight(), maxHeight());
}
public boolean setSize( int w, int h){
public boolean forceSize( int w, int h ){
return setSize( w, w, h, h );
}
public boolean setSize(int minW, int maxW, int minH, int maxH) {
public boolean setSizeWithLimit( int w, int h ){
if ( w < minWidth() || h < minHeight()) {
return false;
} else {
setSize();
if (width() > w || height() > h){
resize(Math.min(width(), w)-1, Math.min(height(), h)-1);
}
return true;
}
}
protected boolean setSize(int minW, int maxW, int minH, int maxH) {
if (minW < minWidth()
|| maxW > maxWidth()
|| minH < minHeight()
|| maxH > maxHeight()){
|| maxH > maxHeight()
|| minW > maxW
|| minH > maxH){
return false;
} else {
//subtract one because rooms are inclusive to their right and bottom sides
resize(left + Random.NormalIntRange(minW, maxW) - 1,
top + Random.NormalIntRange(minH, maxH) - 1);
resize(Random.NormalIntRange(minW, maxW) - 1,
Random.NormalIntRange(minH, maxH) - 1);
return true;
}
}

View File

@ -175,7 +175,8 @@ public class InterlevelScene extends PixelScene {
String errorMsg;
if (error instanceof FileNotFoundException) errorMsg = Messages.get(this, "file_not_found");
else if (error instanceof IOException) errorMsg = Messages.get(this, "io_error");
else if (error.getMessage().equals("old save")) errorMsg = Messages.get(this, "io_error");
else if (error.getMessage() != null &&
error.getMessage().equals("old save")) errorMsg = Messages.get(this, "io_error");
else throw new RuntimeException("fatal error occured while moving between floors", error);