v0.6.0: rooms can now specify allowed locations for traps/water/grass

This commit is contained in:
Evan Debenham 2017-05-06 18:51:15 -04:00
parent 3636a9bb67
commit 3cd27528c0
3 changed files with 112 additions and 39 deletions

View File

@ -24,10 +24,8 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.painters;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Patch; import com.shatteredpixel.shatteredpixeldungeon.levels.Patch;
import com.shatteredpixel.shatteredpixeldungeon.levels.RegularLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.connection.ConnectionRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EmptyRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EmptyRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.Trap; import com.shatteredpixel.shatteredpixeldungeon.levels.traps.Trap;
import com.watabou.utils.PathFinder; import com.watabou.utils.PathFinder;
@ -116,15 +114,15 @@ public abstract class RegularPainter extends Painter {
} }
if (waterFill > 0f) { if (waterFill > 0f) {
paintWater( level ); paintWater( level, rooms );
} }
if (grassFill > 0f){ if (grassFill > 0f){
paintGrass( level ); paintGrass( level, rooms );
} }
if (nTraps > 0){ if (nTraps > 0){
paintTraps( level ); paintTraps( level, rooms );
} }
decorate( level, rooms ); decorate( level, rooms );
@ -249,47 +247,79 @@ public abstract class RegularPainter extends Painter {
return true; return true;
} }
protected void paintWater( Level l ){ protected void paintWater( Level l, ArrayList<Room> rooms ){
boolean[] lake = boolean[] lake = Patch.generate( l.width(), l.height(), waterFill, waterSmoothness, true );
Patch.generate( l.width(), l.height(), waterFill, waterSmoothness, true );
for (int i=0; i < l.length(); i++) {
if (l.map[i] == Terrain.EMPTY && lake[i]) {
l.map[i] = Terrain.WATER;
}
}
}
protected void paintGrass( Level l ) { if (!rooms.isEmpty()){
boolean[] grass = for (Room r : rooms){
Patch.generate( l.width(), l.height(), grassFill, grassSmoothness, true ); for (Point p : r.terrainModifiablePoints()){
int i = l.pointToCell(p);
//adds some chaos to grass distribution, note that this does decrease the fill rate slightly if (lake[i] && l.map[i] == Terrain.EMPTY){
//TODO: analyize statistical changes on fill rate l.map[i] = Terrain.WATER;
for (int i=l.width()+1; i < l.length()-l.width()-1; i++) {
if (l.map[i] == Terrain.EMPTY && grass[i]) {
int count = 1;
for (int n : PathFinder.NEIGHBOURS8) {
if (grass[i + n]) {
count++;
} }
} }
l.map[i] = (Random.Float() < count / 12f) ? Terrain.HIGH_GRASS : Terrain.GRASS;
} }
} else {
for (int i = 0; i < l.length(); i ++) {
if (lake[i] && l.map[i] == Terrain.EMPTY){
l.map[i] = Terrain.WATER;
}
}
}
}
protected void paintGrass( Level l, ArrayList<Room> rooms ) {
boolean[] grass = Patch.generate( l.width(), l.height(), grassFill, grassSmoothness, true );
ArrayList<Integer> grassCells = new ArrayList<>();
if (!rooms.isEmpty()){
for (Room r : rooms){
for (Point p : r.terrainModifiablePoints()){
int i = l.pointToCell(p);
if (grass[i] && l.map[i] == Terrain.EMPTY){
grassCells.add(i);
}
}
}
} else {
for (int i = 0; i < l.length(); i ++) {
if (grass[i] && l.map[i] == Terrain.EMPTY){
grassCells.add(i);
}
}
}
//Adds chaos to grass height distribution. Ratio of high grass depends on fill and smoothing
//Full range is 8.3% to 75%, but most commonly (20% fill with 3 smoothing) is around 60%
//low smoothing, or very low fill, will begin to push the ratio down, normally to 50-30%
for (int i : grassCells) {
int count = 1;
for (int n : PathFinder.NEIGHBOURS8) {
if (grass[i + n]) {
count++;
}
}
l.map[i] = (Random.Float() < count / 12f) ? Terrain.HIGH_GRASS : Terrain.GRASS;
} }
} }
protected void paintTraps( Level l ) { protected void paintTraps( Level l, ArrayList<Room> rooms ) {
ArrayList<Integer> validCells = new ArrayList<>(); ArrayList<Integer> validCells = new ArrayList<>();
for (int i = 0; i < l.length(); i ++) { if (!rooms.isEmpty()){
if (l.map[i] == Terrain.EMPTY){ for (Room r : rooms){
//TODO rooms should probably be able to handle trap placement for (Point p : r.trapPlaceablePoints()){
if (Dungeon.depth == 1){ int i = l.pointToCell(p);
Room r = ((RegularLevel)l).room(i); if (l.map[i] == Terrain.EMPTY){
if (r != null && !(r instanceof ConnectionRoom)){
validCells.add(i); validCells.add(i);
} }
} else { }
}
} else {
for (int i = 0; i < l.length(); i ++) {
if (l.map[i] == Terrain.EMPTY){
validCells.add(i); validCells.add(i);
} }
} }

View File

@ -68,10 +68,6 @@ public class Room extends Rect implements Graph.Node, Bundlable {
return this; return this;
} }
//TODO make abstract
public void paint(Level level){ }
// **** Spatial logic **** // **** Spatial logic ****
//Note: when overriding these YOU MUST store any randomly decided values. //Note: when overriding these YOU MUST store any randomly decided values.
@ -143,6 +139,7 @@ public class Room extends Rect implements Graph.Node, Bundlable {
Random.IntRange( top + m, bottom - m )); Random.IntRange( top + m, bottom - m ));
} }
//a point is only considered to be inside if it is within the 1 tile perimeter
public boolean inside( Point p ) { public boolean inside( Point p ) {
return p.x > left && p.y > top && p.x < right && p.y < bottom; return p.x > left && p.y > top && p.x < right && p.y < bottom;
} }
@ -261,6 +258,44 @@ public class Room extends Rect implements Graph.Node, Bundlable {
connected.clear(); connected.clear();
} }
// **** Painter Logic ****
//TODO make abstract
public void paint(Level level){}
//whether or not a painter can make its own modifications to a specific point
public boolean canModifyTerrain(Point p){
return inside(p);
}
public final ArrayList<Point> terrainModifiablePoints(){
ArrayList<Point> points = new ArrayList<>();
for (int i = left; i <= right; i++) {
for (int j = top; j <= bottom; j++) {
Point p = new Point(i, j);
if (canModifyTerrain(p)) points.add(p);
}
}
return points;
}
//whether or not a painter can place a trap at a specific point
public boolean canPlaceTrap(Point p){
return inside(p);
}
public final ArrayList<Point> trapPlaceablePoints(){
ArrayList<Point> points = new ArrayList<>();
for (int i = left; i <= right; i++) {
for (int j = top; j <= bottom; j++) {
Point p = new Point(i, j);
if (canPlaceTrap(p)) points.add(p);
}
}
return points;
}
// **** Graph.Node interface **** // **** Graph.Node interface ****
@Override @Override

View File

@ -21,8 +21,10 @@
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.connection; package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.connection;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon; import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.watabou.utils.Point;
import com.watabou.utils.Random; import com.watabou.utils.Random;
import java.util.HashMap; import java.util.HashMap;
@ -50,6 +52,12 @@ public abstract class ConnectionRoom extends Room {
else return 4; else return 4;
} }
@Override
public boolean canPlaceTrap(Point p) {
//traps cannot appear in connection rooms on floor 1
return super.canPlaceTrap(p) && Dungeon.depth > 1;
}
private static HashMap<Class<?extends ConnectionRoom>, Float> chances = new LinkedHashMap<>(); private static HashMap<Class<?extends ConnectionRoom>, Float> chances = new LinkedHashMap<>();
static { static {