From 89c2e2b4872e3629c9a60617620b678f8e94b589 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Mon, 9 Nov 2020 17:07:38 -0500 Subject: [PATCH] v0.9.1: added a new fissure room to the caves --- .../rooms/standard/CavesFissureRoom.java | 268 ++++++++++++++++++ .../levels/rooms/standard/StandardRoom.java | 15 +- 2 files changed, 276 insertions(+), 7 deletions(-) create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/CavesFissureRoom.java diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/CavesFissureRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/CavesFissureRoom.java new file mode 100644 index 000000000..ba319fe15 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/CavesFissureRoom.java @@ -0,0 +1,268 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2020 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard; + +import com.shatteredpixel.shatteredpixeldungeon.levels.Level; +import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; +import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter; +import com.watabou.utils.Point; +import com.watabou.utils.PointF; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class CavesFissureRoom extends StandardRoom { + + @Override + public int minWidth() { + return Math.max(7, super.minWidth()); + } + + @Override + public int minHeight() { + return Math.max(7, super.minHeight()); + } + + @Override + public float[] sizeCatProbs() { + return new float[]{9, 3, 1}; + } + + @Override + public boolean canMerge(Level l, Point p, int mergeTerrain) { + if (mergeTerrain == Terrain.CHASM) { + return true; + } else { + int cell = l.pointToCell(pointInside(p, 1)); + return l.map[cell] != Terrain.CHASM; + } + } + + @Override + public void paint(Level level) { + Painter.fill( level, this, Terrain.WALL ); + Painter.fill( level, this, 1 , Terrain.EMPTY ); + + for (Door door : connected.values()) { + door.set( Door.Type.REGULAR ); + } + + PointF center = new PointF(center()); + center.x += 0.5f; + center.y += 0.5f; + + //find the angle of each door from our center point + ArrayList doorAngles = new ArrayList<>(); + for (Door d : connected.values()){ + PointF doorCenter = new PointF(d.x+0.5f, d.y+0.5f); + float doorAngle = angleBetweenPoints(center, doorCenter); + if (doorAngle < 0) doorAngle += 360f; + doorAngles.add(doorAngle); + } + + //generate angles for 2-4 fissure lines, they can't be too close to doors or eachother + ArrayList lineAngles = new ArrayList<>(); + int numLines = 1 + sizeCat.roomValue; + for (int i = 0; i < numLines; i++){ + int tries = 100; + boolean valid; + do { + valid = true; + float lineAngle = Random.Float(0, 360); + for (float doorAngle : doorAngles){ + float angleDiff = Math.abs(lineAngle - doorAngle); + if (angleDiff > 180f) angleDiff = 360f - angleDiff; + if (angleDiff <= (sizeCat == SizeCategory.NORMAL ? 30f : 15f)){ + valid = false; + break; + } + } + + for (float existingLineAngle : lineAngles){ + float angleDiff = Math.abs(lineAngle - existingLineAngle); + if (angleDiff > 180f) angleDiff = 360f - angleDiff; + if (angleDiff <= (numLines == 2 ? 120f : 60f)){ + valid = false; + break; + } + } + + if (valid){ + lineAngles.add(lineAngle); + } + + } while (!valid && --tries > 0); + } + + //just become an empty room if we can't make at least 2 lines + if (lineAngles.size() < 2){ + return; + } + + //fill in each fissure + for(float lineAngle : lineAngles){ + float dX = (float)Math.cos(lineAngle/A - Math.PI/2.0); + float dY = (float)Math.sin(lineAngle/A - Math.PI/2.0); + + boolean horizontal; + if (Math.abs(dX) >= Math.abs(dY)){ + horizontal = true; + dY /= Math.abs(dX); + dX /= Math.abs(dX); + } else { + horizontal = false; + dX /= Math.abs(dY); + dY /= Math.abs(dY); + } + + PointF curr = new PointF(center); + int cell = (int)curr.x + ((int)curr.y)*level.width(); + Painter.set(level, cell, Terrain.CHASM); + do { + if (!horizontal){ + if (level.map[cell-1] == Terrain.EMPTY + && ((curr.x % 1 <= 0.5f) || sizeCat == SizeCategory.GIANT)) { + Painter.set(level, cell - 1, Terrain.CHASM); + } + if (level.map[cell] == Terrain.EMPTY) Painter.set(level, cell, Terrain.CHASM); + if (level.map[cell+1] == Terrain.EMPTY + && ((curr.x % 1 > 0.5f) || sizeCat == SizeCategory.GIANT)) { + Painter.set(level, cell + 1, Terrain.CHASM); + } + } else { + if (level.map[cell-level.width()] == Terrain.EMPTY + && ((curr.y % 1 <= 0.5f) || sizeCat == SizeCategory.GIANT)) { + Painter.set(level, cell - level.width(), Terrain.CHASM); + } + if (level.map[cell] == Terrain.EMPTY) Painter.set(level, cell, Terrain.CHASM); + if (level.map[cell+level.width()] == Terrain.EMPTY + && ((curr.y % 1 > 0.5f) || sizeCat == SizeCategory.GIANT)) { + Painter.set(level, cell + level.width(), Terrain.CHASM); + } + } + + curr.x += dX; + curr.y += dY; + cell = (int)curr.x + ((int)curr.y)*level.width(); + } while (level.map[cell] == Terrain.EMPTY || level.map[cell] == Terrain.CHASM); + + } + + //add chasm to the center in larger rooms + if (lineAngles.size() >= 3){ + if (sizeCat == SizeCategory.GIANT){ + Painter.fill(level, (int)center.x-2, (int)center.y-2, 5, 5, Terrain.CHASM); + } else { + Painter.fill(level, (int)center.x-1, (int)center.y-1, 3, 3, Terrain.CHASM); + } + } + + //draw bridges for the chasms + if (lineAngles.size() == 2){ + buildBridge(level, Random.element(lineAngles), center, 1); + } else { + for (float angle : lineAngles){ + buildBridge(level, angle, center, sizeCat.roomValue); + } + } + + for (Door door : connected.values()) { + Painter.drawInside( level, this, door, 1, Terrain.EMPTY); + } + + } + + private void buildBridge( Level level, float fisssureAngle, PointF center, int centerMargin){ + float dX = (float)Math.cos(fisssureAngle/A - Math.PI/2.0); + float dY = (float)Math.sin(fisssureAngle/A - Math.PI/2.0); + //horizontal bridge + if (Math.abs(dY) >= Math.abs(dX)){ + int Y; + if (dY > 0) Y = Random.IntRange((int)center.y+centerMargin, bottom-2); + else Y = Random.IntRange(top+2, (int)center.y-centerMargin); + + boolean foundChasm = false; + if (dX <= 0) { + for (int X = left + 1; X <= right - 1; X++) { + int cell = X + Y * level.width(); + if (level.map[cell] == Terrain.CHASM) { + foundChasm = true; + Painter.set(level, cell, Terrain.EMPTY_SP); + } else if (foundChasm) { + break; + } + } + } else { + for (int X = right-1; X >= left+1; X--) { + int cell = X + Y * level.width(); + if (level.map[cell] == Terrain.CHASM) { + foundChasm = true; + Painter.set(level, cell, Terrain.EMPTY_SP); + } else if (foundChasm) { + break; + } + } + } + + //vertical bridge + } else { + int X; + if (dX > 0) X = Random.IntRange((int)center.x+centerMargin, right-2); + else X = Random.IntRange(left+2, (int)center.x-centerMargin); + + boolean foundChasm = false; + if (dY <= 0) { + for (int Y = top + 1; Y <= bottom - 1; Y++) { + int cell = X + Y * level.width(); + if (level.map[cell] == Terrain.CHASM) { + foundChasm = true; + Painter.set(level, cell, Terrain.EMPTY_SP); + } else if (foundChasm){ + break; + } + } + } else { + for (int Y = bottom-1; Y >= top + 1; Y--) { + int cell = X + Y * level.width(); + if (level.map[cell] == Terrain.CHASM) { + foundChasm = true; + Painter.set(level, cell, Terrain.EMPTY_SP); + } else if (foundChasm){ + break; + } + } + } + + } + } + + private static final double A = 180 / Math.PI; + + protected static float angleBetweenPoints( PointF from, PointF to ){ + double m = (to.y - from.y)/(to.x - from.x); + + float angle = (float)(A*(Math.atan(m) + Math.PI/2.0)); + if (from.x > to.x) angle -= 180f; + return angle; + } + +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/StandardRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/StandardRoom.java index 29383f384..d7a4886cc 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/StandardRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/StandardRoom.java @@ -122,6 +122,7 @@ public abstract class StandardRoom extends Room { rooms.add(CellBlockRoom.class); rooms.add(CaveRoom.class); + rooms.add(CavesFissureRoom.class); rooms.add(CirclePitRoom.class); rooms.add(HallwayRoom.class); @@ -147,21 +148,21 @@ public abstract class StandardRoom extends Room { private static float[][] chances = new float[27][]; static { - chances[1] = new float[]{15, 10,10,5, 0,0,0, 0,0, 0,0,0, 0,0,0, 1,0,1,0,1,0,1,1,0,0}; - chances[2] = new float[]{15, 10,10,5, 0,0,0, 0,0, 0,0,0, 0,0,0, 1,1,1,1,1,1,1,1,1,1}; + chances[1] = new float[]{15, 10,10,5, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 1,0,1,0,1,0,1,1,0,0}; + chances[2] = new float[]{15, 10,10,5, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 1,1,1,1,1,1,1,1,1,1}; chances[4] = chances[3] = chances[2]; - chances[5] = new float[]{15, 10,10,0, 0,0,0, 0,0, 0,0,0, 0,0,0, 0,0,0,0,0,0,0,0,0,0}; + chances[5] = new float[]{15, 10,10,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0,0,0,0,0,0,0,0}; - chances[6] = new float[]{15, 0,0,0, 10,10,5, 0,0, 0,0,0, 0,0,0, 1,1,1,1,1,1,1,1,1,1}; + chances[6] = new float[]{15, 0,0,0, 10,10,5, 0,0,0, 0,0,0, 0,0,0, 1,1,1,1,1,1,1,1,1,1}; chances[10] = chances[9] = chances[8] = chances[7] = chances[6]; - chances[11] = new float[]{20, 0,0,0, 0,0,0, 15,5, 0,0,0, 0,0,0, 1,1,1,1,1,1,1,1,1,1}; + chances[11] = new float[]{20, 0,0,0, 0,0,0, 10,10,5, 0,0,0, 0,0,0, 1,1,1,1,1,1,1,1,1,1}; chances[15] = chances[14] = chances[13] = chances[12] = chances[11]; - chances[16] = new float[]{15, 0,0,0, 0,0,0, 0,0, 10,10,5, 0,0,0, 1,1,1,1,1,1,1,1,1,1}; + chances[16] = new float[]{15, 0,0,0, 0,0,0, 0,0,0, 10,10,5, 0,0,0, 1,1,1,1,1,1,1,1,1,1}; chances[20] = chances[19] = chances[18] = chances[17] = chances[16]; - chances[21] = new float[]{15, 0,0,0, 0,0,0, 0,0, 0,0,0, 10,10,5, 1,1,1,1,1,1,1,1,1,1}; + chances[21] = new float[]{15, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 10,10,5, 1,1,1,1,1,1,1,1,1,1}; chances[26] = chances[25] = chances[24] = chances[23] = chances[22] = chances[21]; }