parent
f71fa66c1e
commit
1ca0b9e0e9
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 9.5 KiB |
Binary file not shown.
@ -0,0 +1,37 @@ |
||||
package mightypork.gamecore.util.error; |
||||
|
||||
|
||||
import java.io.IOException; |
||||
|
||||
|
||||
/** |
||||
* Thrown when data could not be read successfully. |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public class CorruptDataException extends IOException { |
||||
|
||||
public CorruptDataException() |
||||
{ |
||||
super(); |
||||
} |
||||
|
||||
|
||||
public CorruptDataException(String message, Throwable cause) |
||||
{ |
||||
super(message, cause); |
||||
} |
||||
|
||||
|
||||
public CorruptDataException(String message) |
||||
{ |
||||
super(message); |
||||
} |
||||
|
||||
|
||||
public CorruptDataException(Throwable cause) |
||||
{ |
||||
super(cause); |
||||
} |
||||
|
||||
} |
@ -1,37 +0,0 @@ |
||||
package mightypork.gamecore.util.error; |
||||
|
||||
|
||||
import java.io.IOException; |
||||
|
||||
|
||||
/** |
||||
* To be used when a data could not be read successfully. |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public class CorruptedDataException extends IOException { |
||||
|
||||
public CorruptedDataException() |
||||
{ |
||||
super(); |
||||
} |
||||
|
||||
|
||||
public CorruptedDataException(String message, Throwable cause) |
||||
{ |
||||
super(message, cause); |
||||
} |
||||
|
||||
|
||||
public CorruptedDataException(String message) |
||||
{ |
||||
super(message); |
||||
} |
||||
|
||||
|
||||
public CorruptedDataException(Throwable cause) |
||||
{ |
||||
super(cause); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,95 @@ |
||||
package mightypork.gamecore.util.math.algo; |
||||
|
||||
|
||||
import java.util.Arrays; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
import java.util.Random; |
||||
|
||||
import mightypork.gamecore.util.math.Calc; |
||||
|
||||
|
||||
/** |
||||
* Move lists, bit masks and other utilities |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public class Moves { |
||||
|
||||
public static final byte BIT_NW = (byte) 0b10000000; |
||||
public static final byte BIT_N = (byte) 0b01000000; |
||||
public static final byte BIT_NE = (byte) 0b00100000; |
||||
public static final byte BIT_E = (byte) 0b00010000; |
||||
public static final byte BIT_SE = (byte) 0b00001000; |
||||
public static final byte BIT_S = (byte) 0b00000100; |
||||
public static final byte BIT_SW = (byte) 0b00000010; |
||||
public static final byte BIT_W = (byte) 0b00000001; |
||||
|
||||
public static final byte BITS_CARDINAL = BIT_N | BIT_S | BIT_E | BIT_W; |
||||
public static final byte BITS_DIAGONAL = BIT_NE | BIT_NW | BIT_SE | BIT_SW; |
||||
|
||||
public static final byte BITS_NW_CORNER = BIT_W | BIT_NW | BIT_N; |
||||
public static final byte BITS_NE_CORNER = BIT_E | BIT_NE | BIT_N; |
||||
public static final byte BITS_SW_CORNER = BIT_W | BIT_SW | BIT_S; |
||||
public static final byte BITS_SE_CORNER = BIT_E | BIT_SE | BIT_S; |
||||
|
||||
public static final Move NW = Move.make(-1, -1); |
||||
public static final Move N = Move.make(0, -1); |
||||
public static final Move NE = Move.make(1, -1); |
||||
public static final Move E = Move.make(1, 0); |
||||
public static final Move SE = Move.make(1, 1); |
||||
public static final Move S = Move.make(0, 1); |
||||
public static final Move SW = Move.make(-1, 1); |
||||
public static final Move W = Move.make(-1, 0); |
||||
|
||||
//@formatter:off
|
||||
/** All sides, in the order of bits. */ |
||||
public final static List<Move> ALL_SIDES = Collections.unmodifiableList(Arrays.asList( |
||||
NW, |
||||
N, |
||||
NE, |
||||
E, |
||||
SE, |
||||
S, |
||||
SW, |
||||
W |
||||
)); |
||||
|
||||
public final static List<Move> CARDINAL_SIDES = Collections.unmodifiableList(Arrays.asList( |
||||
N, |
||||
E, |
||||
S, |
||||
W |
||||
)); |
||||
|
||||
//@formatter:on
|
||||
|
||||
/** |
||||
* Get element from all sides |
||||
* |
||||
* @param i side index |
||||
* @return the side coord |
||||
*/ |
||||
public static Move getSide(int i) |
||||
{ |
||||
return ALL_SIDES.get(i); |
||||
} |
||||
|
||||
|
||||
public static byte getBit(int i) |
||||
{ |
||||
return (byte) (1 << (7 - i)); |
||||
} |
||||
|
||||
|
||||
public static Move randomCardinal() |
||||
{ |
||||
return Calc.pick(CARDINAL_SIDES); |
||||
} |
||||
|
||||
|
||||
public static Move randomCardinal(Random rand) |
||||
{ |
||||
return Calc.pick(rand, CARDINAL_SIDES); |
||||
} |
||||
} |
@ -1,79 +0,0 @@ |
||||
package mightypork.gamecore.util.math.algo; |
||||
|
||||
|
||||
import mightypork.gamecore.util.math.Calc; |
||||
|
||||
|
||||
public class Sides { |
||||
|
||||
public static final byte MASK_NW = (byte) 0b10000000; |
||||
public static final byte MASK_N = (byte) 0b01000000; |
||||
public static final byte MASK_NE = (byte) 0b00100000; |
||||
public static final byte MASK_E = (byte) 0b00010000; |
||||
public static final byte MASK_SE = (byte) 0b00001000; |
||||
public static final byte MASK_S = (byte) 0b00000100; |
||||
public static final byte MASK_SW = (byte) 0b00000010; |
||||
public static final byte MASK_W = (byte) 0b00000001; |
||||
|
||||
public static final byte MASK_CARDINAL = MASK_N | MASK_S | MASK_E | MASK_W; |
||||
public static final byte MASK_DIAGONAL = MASK_NE | MASK_NW | MASK_SE | MASK_SW; |
||||
|
||||
public static final byte NW_CORNER = MASK_W | MASK_NW | MASK_N; |
||||
public static final byte NE_CORNER = MASK_E | MASK_NE | MASK_N; |
||||
public static final byte SW_CORNER = MASK_W | MASK_SW | MASK_S; |
||||
public static final byte SE_CORNER = MASK_E | MASK_SE | MASK_S; |
||||
|
||||
public static final Step NW = Step.make(-1, -1); |
||||
public static final Step N = Step.make(0, -1); |
||||
public static final Step NE = Step.make(1, -1); |
||||
public static final Step E = Step.make(1, 0); |
||||
public static final Step SE = Step.make(1, 1); |
||||
public static final Step S = Step.make(0, 1); |
||||
public static final Step SW = Step.make(-1, 1); |
||||
public static final Step W = Step.make(-1, 0); |
||||
|
||||
//@formatter:off
|
||||
/** All sides, in the order of bits. */ |
||||
public final static Step[] ALL_SIDES = { |
||||
NW, |
||||
N, |
||||
NE, |
||||
E, |
||||
SE, |
||||
S, |
||||
SW, |
||||
W |
||||
}; |
||||
|
||||
public final static Step[] CARDINAL_SIDES = { |
||||
N, |
||||
E, |
||||
S, |
||||
W |
||||
}; |
||||
|
||||
//@formatter:on
|
||||
|
||||
/** |
||||
* Get element from all sides |
||||
* |
||||
* @param i side index |
||||
* @return the side coord |
||||
*/ |
||||
public static Step get(int i) |
||||
{ |
||||
return ALL_SIDES[i]; |
||||
} |
||||
|
||||
|
||||
public static byte bit(int i) |
||||
{ |
||||
return (byte) (1 << (7 - i)); |
||||
} |
||||
|
||||
|
||||
public static Step randomCardinal() |
||||
{ |
||||
return CARDINAL_SIDES[Calc.randInt(0, 3)]; |
||||
} |
||||
} |
@ -1,50 +0,0 @@ |
||||
package mightypork.gamecore.util.objects; |
||||
|
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import mightypork.gamecore.logging.Log; |
||||
|
||||
|
||||
/** |
||||
* Object utils class
|
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public class ObjectUtils { |
||||
|
||||
public static Object fallback(Object... options) |
||||
{ |
||||
for (final Object o : options) { |
||||
if (o != null) return o; |
||||
} |
||||
return null; // error
|
||||
} |
||||
|
||||
|
||||
public static <T> String arrayToString(T[] arr) |
||||
{ |
||||
final StringBuilder sb = new StringBuilder(); |
||||
|
||||
sb.append('['); |
||||
final boolean first = true; |
||||
for (final T o : arr) { |
||||
if (!first) sb.append(','); |
||||
sb.append(Log.str(o)); |
||||
} |
||||
sb.append(']'); |
||||
|
||||
return sb.toString(); |
||||
} |
||||
|
||||
|
||||
public static <T> List<T> arrayToList(T[] objs) |
||||
{ |
||||
final ArrayList<T> list = new ArrayList<>(); |
||||
for (final T o : objs) { |
||||
list.add(o); |
||||
} |
||||
return list; |
||||
} |
||||
} |
@ -0,0 +1,119 @@ |
||||
/* |
||||
* The Alphanum Algorithm is an improved sorting algorithm for strings |
||||
* containing numbers. Instead of sorting numbers in ASCII order like |
||||
* a standard sort, this algorithm sorts numbers in numeric order. |
||||
* |
||||
* The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
|
||||
* |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or any later version. |
||||
* |
||||
* This library 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 |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||||
* |
||||
*/ |
||||
|
||||
package mightypork.gamecore.util.strings; |
||||
|
||||
|
||||
import java.util.Comparator; |
||||
|
||||
|
||||
/** |
||||
* String comparator taking care of strings with numbers. |
||||
* |
||||
* @author Daniel Migowski |
||||
* @author Andre Bogus |
||||
* @author David Koelle |
||||
* @author MightyPork |
||||
*/ |
||||
public class AlphanumComparator implements Comparator<String> { |
||||
|
||||
public static final AlphanumComparator instance = new AlphanumComparator(); |
||||
|
||||
|
||||
private final boolean isDigit(char ch) |
||||
{ |
||||
return ch >= '0' && ch <= '9'; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Length of string is passed in for improved efficiency (only need to |
||||
* calculate it once) |
||||
**/ |
||||
private final String getChunk(String s, int slength, int marker) |
||||
{ |
||||
final StringBuilder chunk = new StringBuilder(); |
||||
char c = s.charAt(marker); |
||||
chunk.append(c); |
||||
marker++; |
||||
|
||||
if (isDigit(c)) { |
||||
while (marker < slength) { |
||||
c = s.charAt(marker); |
||||
if (!isDigit(c)) break; |
||||
chunk.append(c); |
||||
marker++; |
||||
} |
||||
} else { |
||||
while (marker < slength) { |
||||
c = s.charAt(marker); |
||||
if (isDigit(c)) break; |
||||
chunk.append(c); |
||||
marker++; |
||||
} |
||||
} |
||||
return chunk.toString(); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public int compare(String s1, String s2) |
||||
{ |
||||
int thisMarker = 0; |
||||
int thatMarker = 0; |
||||
final int s1Length = s1.length(); |
||||
final int s2Length = s2.length(); |
||||
|
||||
while (thisMarker < s1Length && thatMarker < s2Length) { |
||||
final String thisChunk = getChunk(s1, s1Length, thisMarker); |
||||
thisMarker += thisChunk.length(); |
||||
|
||||
final String thatChunk = getChunk(s2, s2Length, thatMarker); |
||||
thatMarker += thatChunk.length(); |
||||
|
||||
// If both chunks contain numeric characters, sort them numerically
|
||||
int result = 0; |
||||
if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) { |
||||
// Simple chunk comparison by length.
|
||||
final int thisChunkLength = thisChunk.length(); |
||||
result = thisChunkLength - thatChunk.length(); |
||||
// If equal, the first different number counts
|
||||
if (result == 0) { |
||||
for (int i = 0; i < thisChunkLength; i++) { |
||||
result = thisChunk.charAt(i) - thatChunk.charAt(i); |
||||
if (result != 0) { |
||||
return result; |
||||
} |
||||
} |
||||
} |
||||
} else { |
||||
result = thisChunk.compareTo(thatChunk); |
||||
} |
||||
|
||||
if (result != 0) return result; |
||||
} |
||||
|
||||
return s1Length - s2Length; |
||||
} |
||||
} |
@ -0,0 +1,253 @@ |
||||
package mightypork.rogue.world.gen; |
||||
|
||||
|
||||
import java.util.Collections; |
||||
import java.util.Iterator; |
||||
import java.util.LinkedList; |
||||
import java.util.List; |
||||
import java.util.Random; |
||||
|
||||
import mightypork.gamecore.util.math.Range; |
||||
import mightypork.gamecore.util.math.algo.Coord; |
||||
import mightypork.rogue.world.World; |
||||
import mightypork.rogue.world.entity.Entity; |
||||
import mightypork.rogue.world.item.Item; |
||||
import mightypork.rogue.world.level.Level; |
||||
|
||||
|
||||
public class LevelBuilder { |
||||
|
||||
public static enum BuildOrder |
||||
{ |
||||
FIRST, MIDDLE, LAST |
||||
} |
||||
|
||||
private class RoomEntry { |
||||
|
||||
int count; |
||||
RoomBuilder room; |
||||
boolean important; |
||||
|
||||
|
||||
public RoomEntry(RoomBuilder room, int count, boolean important) |
||||
{ |
||||
this.count = count; |
||||
this.room = room; |
||||
this.important = important; |
||||
} |
||||
} |
||||
|
||||
private class ItemEntry { |
||||
|
||||
Item item; |
||||
boolean important; |
||||
|
||||
|
||||
public ItemEntry(Item item, boolean important) |
||||
{ |
||||
this.item = item; |
||||
this.important = important; |
||||
} |
||||
} |
||||
|
||||
private class EntityEntry { |
||||
|
||||
Entity entity; |
||||
boolean important; |
||||
|
||||
|
||||
public EntityEntry(Entity item, boolean important) |
||||
{ |
||||
this.entity = item; |
||||
this.important = important; |
||||
} |
||||
} |
||||
|
||||
private final ScratchMap map; |
||||
private final Random rand; |
||||
private boolean built; |
||||
|
||||
private final LinkedList<RoomEntry> roomsFirst = new LinkedList<>(); |
||||
private final LinkedList<RoomEntry> roomsMiddle = new LinkedList<>(); |
||||
private final LinkedList<RoomEntry> roomsLast = new LinkedList<>(); |
||||
|
||||
private final LinkedList<ItemEntry> items = new LinkedList<>(); |
||||
private final LinkedList<EntityEntry> entities = new LinkedList<>(); |
||||
|
||||
|
||||
/** |
||||
* make a new level builder instance. |
||||
* |
||||
* @param max_size max map size (square side - tiles) |
||||
* @param theme tiles theme |
||||
* @param seed level seed |
||||
*/ |
||||
public LevelBuilder(int max_size, MapTheme theme, long seed) |
||||
{ |
||||
this.rand = new Random(seed); |
||||
this.map = new ScratchMap(max_size, theme, rand); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add a single room to the room buffer. |
||||
* |
||||
* @param room room builder |
||||
* @param order build order |
||||
* @param important try harder and throw error on fail |
||||
*/ |
||||
public void addRoom(RoomBuilder room, BuildOrder order, boolean important) |
||||
{ |
||||
addRoom(room, Range.make(1, 1), order, important); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add multiple rooms of the type to the room buffer. |
||||
* |
||||
* @param room room builder |
||||
* @param count number of rooms to build |
||||
* @param order build order |
||||
* @param important try harder and throw error on fail |
||||
*/ |
||||
public void addRoom(RoomBuilder room, Range count, BuildOrder order, boolean important) |
||||
{ |
||||
final List<RoomEntry> list; |
||||
|
||||
switch (order) { |
||||
case FIRST: |
||||
list = roomsFirst; |
||||
break; |
||||
|
||||
default: |
||||
case MIDDLE: |
||||
list = roomsMiddle; |
||||
break; |
||||
|
||||
case LAST: |
||||
list = roomsLast; |
||||
break; |
||||
} |
||||
|
||||
list.add(new RoomEntry(room, count.randInt(rand), important)); |
||||
} |
||||
|
||||
|
||||
private void buildRooms(LinkedList<RoomEntry> list) |
||||
{ |
||||
while (!list.isEmpty()) { |
||||
|
||||
Collections.shuffle(list, rand); |
||||
|
||||
for (final Iterator<RoomEntry> iter = list.iterator(); iter.hasNext();) { |
||||
final RoomEntry rge = iter.next(); |
||||
|
||||
map.addRoom(rge.room, rge.important); |
||||
|
||||
if ((--rge.count) <= 0) { |
||||
iter.remove(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
private void buildCorridors() throws WorldGenError |
||||
{ |
||||
map.buildCorridors(); |
||||
} |
||||
|
||||
|
||||
private void buildEntities() |
||||
{ |
||||
for (final EntityEntry entry : entities) { |
||||
final int tries = entry.important ? 200 : 50; |
||||
final boolean success = map.addEntityInMap(entry.entity, tries); |
||||
|
||||
if (entry.important && !success) { |
||||
throw new WorldGenError("Could not place an important entity: " + entry.entity); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
private void buildItems() |
||||
{ |
||||
for (final ItemEntry entry : items) { |
||||
final int tries = entry.important ? 200 : 50; |
||||
final boolean success = map.addItemInMap(entry.item, tries); |
||||
|
||||
if (entry.important && !success) { |
||||
throw new WorldGenError("Could not place an important item: " + entry.item); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
private void writeToMap() |
||||
{ |
||||
buildRooms(roomsFirst); |
||||
buildRooms(roomsMiddle); |
||||
buildRooms(roomsLast); |
||||
buildCorridors(); |
||||
|
||||
map.fixGlitches(); |
||||
|
||||
buildItems(); |
||||
buildEntities(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Write to a new level instance. |
||||
* |
||||
* @param world level's world |
||||
* @return the level |
||||
* @throws WorldGenError on error in generation |
||||
*/ |
||||
public Level build(World world) throws WorldGenError |
||||
{ |
||||
if (built) { |
||||
throw new WorldGenError("Level already built."); |
||||
} |
||||
built = true; |
||||
|
||||
writeToMap(); |
||||
|
||||
final Coord size = map.getNeededSize(); |
||||
final Level lvl = new Level(size.x, size.y); |
||||
lvl.setWorld(world); // important for creating entities
|
||||
|
||||
map.writeToLevel(lvl); |
||||
|
||||
return lvl; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add an item to be added to the level when tiles are built. |
||||
* |
||||
* @param item item to add |
||||
* @param important try harder and throw error on fail |
||||
* @throws WorldGenError on fail |
||||
*/ |
||||
public void addItem(Item item, boolean important) throws WorldGenError |
||||
{ |
||||
items.add(new ItemEntry(item, important)); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Add an entity to be added to the level when tiles are built.<br> |
||||
* It's EID will be assigned during writing to level. |
||||
* |
||||
* @param entity entity to add |
||||
* @param important try harder and throw error on fail |
||||
* @throws WorldGenError on fail |
||||
*/ |
||||
public void addEntity(Entity entity, boolean important) throws WorldGenError |
||||
{ |
||||
entities.add(new EntityEntry(entity, important)); |
||||
} |
||||
|
||||
} |
@ -1,124 +0,0 @@ |
||||
package mightypork.rogue.world.gen; |
||||
|
||||
|
||||
import java.util.Random; |
||||
|
||||
import mightypork.gamecore.logging.Log; |
||||
import mightypork.gamecore.util.math.Calc; |
||||
import mightypork.gamecore.util.math.algo.Coord; |
||||
import mightypork.rogue.world.World; |
||||
import mightypork.rogue.world.entity.Entities; |
||||
import mightypork.rogue.world.entity.Entity; |
||||
import mightypork.rogue.world.gen.rooms.Rooms; |
||||
import mightypork.rogue.world.gen.themes.ThemeBrick; |
||||
import mightypork.rogue.world.item.Items; |
||||
import mightypork.rogue.world.level.Level; |
||||
|
||||
|
||||
public class LevelGenerator { |
||||
|
||||
public static final MapTheme DUNGEON_THEME = new ThemeBrick(); |
||||
|
||||
|
||||
@SuppressWarnings("fallthrough") |
||||
public static Level build(World world, long seed, int level, MapTheme theme, boolean lastLevel) throws WorldGenError |
||||
{ |
||||
Log.f3("Generating level of complexity: " + level); |
||||
|
||||
final Random rand = new Random(seed + 13); |
||||
|
||||
final int max_size = 128; |
||||
|
||||
final ScratchMap map = new ScratchMap(max_size, theme, rand); |
||||
|
||||
// start
|
||||
if (!map.addRoom(Rooms.ENTRANCE, true)) { |
||||
throw new WorldGenError("Could not place entrance room."); |
||||
} |
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 1 + level, (int) (1 + level * 1.5)); i++) { |
||||
map.addRoom(Rooms.BASIC, false); |
||||
|
||||
// spice it up with dead ends
|
||||
if (rand.nextInt(6) > 0) map.addRoom(Rooms.DEAD_END, false); |
||||
} |
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 1, (int) Math.ceil(level / 2D)); i++) { |
||||
map.addRoom(Rooms.TREASURE, false); |
||||
} |
||||
|
||||
if (!lastLevel) { |
||||
if (!map.addRoom(Rooms.EXIT, true)) { |
||||
throw new WorldGenError("Could not place exit room."); |
||||
} |
||||
} |
||||
|
||||
if (lastLevel) { |
||||
if (!map.addRoom(Rooms.BOSS, true)) { |
||||
throw new WorldGenError("Could not place boss room."); |
||||
} |
||||
} |
||||
|
||||
map.addRoom(Rooms.HEART_ROOM, true); |
||||
|
||||
|
||||
map.buildCorridors(); |
||||
|
||||
switch (level) { |
||||
default: |
||||
case 3: |
||||
case 2: |
||||
if (rand.nextInt(2) == 0) map.putItemInMap(Items.CLUB.createItemDamaged(30), 50); |
||||
case 1: |
||||
if (rand.nextInt(2) == 0) map.putItemInMap(Items.ROCK.createItemDamaged(10), 50); |
||||
} |
||||
|
||||
if (level == 1) { |
||||
map.putItemInMap(Items.BONE.createItemDamaged(20), 60); |
||||
} |
||||
|
||||
if (level == 2) { |
||||
map.putItemInMap(Items.CLUB.createItemDamaged(50), 60); |
||||
} |
||||
|
||||
if (level == 6) { |
||||
map.putItemInMap(Items.SWORD.createItemDamaged(60), 200); |
||||
} |
||||
|
||||
if (level == 4) { |
||||
map.putItemInMap(Items.HAMMER.createItemDamaged(40), 100); |
||||
} |
||||
|
||||
// entities - random rats
|
||||
|
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 2 + level * 2, 5 + level * 3); i++) { |
||||
Entity e; |
||||
|
||||
if (level > 2 && rand.nextInt(level - 2 + 1) != 0) { |
||||
e = Entities.RAT_BROWN.createEntity(); |
||||
} else { |
||||
e = Entities.RAT_GRAY.createEntity(); |
||||
} |
||||
|
||||
map.putEntityInMap(e, 30); |
||||
|
||||
if (rand.nextInt(6 + level / 2) == 0) { |
||||
map.putItemInMap(Items.CHEESE.createItem(), 10); |
||||
} |
||||
|
||||
if (rand.nextInt(6) == 0) { |
||||
map.putItemInMap(Items.MEAT.createItem(), 10); |
||||
} |
||||
} |
||||
|
||||
|
||||
final Coord size = map.getNeededSize(); |
||||
final Level lvl = new Level(size.x, size.y); |
||||
lvl.setWorld(world); // important for creating entities
|
||||
|
||||
map.writeToLevel(lvl); |
||||
|
||||
return lvl; |
||||
} |
||||
} |
@ -0,0 +1,28 @@ |
||||
package mightypork.rogue.world.gen; |
||||
|
||||
|
||||
import mightypork.rogue.world.gen.rooms.*; |
||||
import mightypork.rogue.world.item.Item; |
||||
|
||||
|
||||
public class Rooms { |
||||
|
||||
public static final RoomBuilder BASIC = new BasicRoom(); |
||||
public static final RoomBuilder STORAGE = new StorageRoom(); |
||||
public static final RoomBuilder DEAD_END = new DeadEndRoom(); |
||||
public static final RoomBuilder ENTRANCE = new EntranceRoom(); |
||||
public static final RoomBuilder EXIT = new ExitRoom(); |
||||
public static final RoomBuilder BOSS = new BossRoom(); |
||||
|
||||
|
||||
public static RoomBuilder treasure(Item item) |
||||
{ |
||||
return new TreasureChestRoom(item); |
||||
} |
||||
|
||||
|
||||
public static RoomBuilder shrine(Item item) |
||||
{ |
||||
return new ItemShrineRoom(item); |
||||
} |
||||
} |
@ -1,16 +0,0 @@ |
||||
package mightypork.rogue.world.gen.rooms; |
||||
|
||||
|
||||
import mightypork.rogue.world.gen.RoomBuilder; |
||||
|
||||
|
||||
public class Rooms { |
||||
|
||||
public static final RoomBuilder BASIC = new BasicRoom(); |
||||
public static final RoomBuilder TREASURE = new TreasureRoom(); |
||||
public static final RoomBuilder DEAD_END = new DeadEndRoom(); |
||||
public static final RoomBuilder ENTRANCE = new EntranceRoom(); |
||||
public static final RoomBuilder EXIT = new ExitRoom(); |
||||
public static final RoomBuilder BOSS = new BossRoom(); |
||||
public static final RoomBuilder HEART_ROOM = new HeartPieceRoom(); |
||||
} |
@ -0,0 +1,50 @@ |
||||
package mightypork.rogue.world.gen.rooms; |
||||
|
||||
|
||||
import java.util.Random; |
||||
|
||||
import mightypork.gamecore.util.math.Calc; |
||||
import mightypork.gamecore.util.math.algo.Coord; |
||||
import mightypork.rogue.world.gen.MapTheme; |
||||
import mightypork.rogue.world.gen.ScratchMap; |
||||
import mightypork.rogue.world.item.Items; |
||||
|
||||
|
||||
public class StorageRoom extends SecretRoom { |
||||
|
||||
@Override |
||||
protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max) |
||||
{ |
||||
int maxStuff = 3; |
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 0, 1); i++) { |
||||
map.addItemInArea(Items.SANDWICH.createItem(), min, max, 50); |
||||
if (--maxStuff == 0) break; |
||||
} |
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 0, 2); i++) { |
||||
map.addItemInArea(Items.TWIG.createItemDamaged(40), min, max, 50); |
||||
if (--maxStuff == 0) break; |
||||
} |
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 0, 2); i++) { |
||||
map.addItemInArea(Items.BONE.createItemDamaged(40), min, max, 50); |
||||
if (--maxStuff == 0) break; |
||||
} |
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 0, 2); i++) { |
||||
map.addItemInArea(Items.MEAT.createItem(), min, max, 50); |
||||
if (--maxStuff == 0) break; |
||||
} |
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 0, 2); i++) { |
||||
map.addItemInArea(Items.CHEESE.createItem(), min, max, 50); |
||||
if (--maxStuff == 0) break; |
||||
} |
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 0, 1); i++) { |
||||
map.addItemInArea(Items.ROCK.createItemDamaged(30), min, max, 50); |
||||
if (--maxStuff == 0) break; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,33 @@ |
||||
package mightypork.rogue.world.gen.rooms; |
||||
|
||||
|
||||
import java.util.Random; |
||||
|
||||
import mightypork.gamecore.util.math.algo.Coord; |
||||
import mightypork.rogue.world.gen.MapTheme; |
||||
import mightypork.rogue.world.gen.ScratchMap; |
||||
import mightypork.rogue.world.gen.TileProtectLevel; |
||||
import mightypork.rogue.world.item.Item; |
||||
|
||||
|
||||
public class TreasureChestRoom extends ItemShrineRoom { |
||||
|
||||
public TreasureChestRoom(Item item) |
||||
{ |
||||
super(item); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max) |
||||
{ |
||||
// set tile
|
||||
final Coord center = min.add(2, 2); |
||||
|
||||
map.set(center, theme.chest()); |
||||
map.protect(center, TileProtectLevel.STRONG); |
||||
|
||||
// drop item
|
||||
super.buildExtras(map, theme, rand, min, max); |
||||
} |
||||
} |
@ -1,38 +0,0 @@ |
||||
package mightypork.rogue.world.gen.rooms; |
||||
|
||||
|
||||
import java.util.Random; |
||||
|
||||
import mightypork.gamecore.util.math.Calc; |
||||
import mightypork.gamecore.util.math.algo.Coord; |
||||
import mightypork.rogue.world.gen.MapTheme; |
||||
import mightypork.rogue.world.gen.ScratchMap; |
||||
import mightypork.rogue.world.item.Items; |
||||
|
||||
|
||||
public class TreasureRoom extends SecretRoom { |
||||
|
||||
@Override |
||||
protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max) |
||||
{ |
||||
for (int i = 0; i < Calc.randInt(rand, 0, 1); i++) { |
||||
map.putItemInArea(Items.SANDWICH.createItem(), min, max, 50); |
||||
} |
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 0, 2); i++) { |
||||
map.putItemInArea(Items.BONE.createItemDamaged(20), min, max, 50); |
||||
} |
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 0, 1); i++) { |
||||
map.putItemInArea(Items.ROCK.createItemDamaged(30), min, max, 50); |
||||
} |
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 0, 3); i++) { |
||||
map.putItemInArea(Items.MEAT.createItem(), min, max, 50); |
||||
} |
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 0, 2); i++) { |
||||
map.putItemInArea(Items.CHEESE.createItem(), min, max, 50); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,45 @@ |
||||
package mightypork.rogue.world.item.impl.weapons; |
||||
|
||||
|
||||
import mightypork.rogue.Res; |
||||
import mightypork.rogue.world.item.ItemModel; |
||||
import mightypork.rogue.world.item.ItemRenderer; |
||||
import mightypork.rogue.world.item.impl.ItemBaseWeapon; |
||||
import mightypork.rogue.world.item.render.QuadItemRenderer; |
||||
|
||||
|
||||
public class ItemKnife extends ItemBaseWeapon { |
||||
|
||||
public ItemKnife(ItemModel model) |
||||
{ |
||||
super(model); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected ItemRenderer makeRenderer() |
||||
{ |
||||
return new QuadItemRenderer(this, Res.getTxQuad("item.knife")); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public int getAttackPoints() |
||||
{ |
||||
return 4; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public int getMaxUses() |
||||
{ |
||||
return 60; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public String getVisualName() |
||||
{ |
||||
return "Knife"; |
||||
} |
||||
} |
@ -0,0 +1,45 @@ |
||||
package mightypork.rogue.world.item.impl.weapons; |
||||
|
||||
|
||||
import mightypork.rogue.Res; |
||||
import mightypork.rogue.world.item.ItemModel; |
||||
import mightypork.rogue.world.item.ItemRenderer; |
||||
import mightypork.rogue.world.item.impl.ItemBaseWeapon; |
||||
import mightypork.rogue.world.item.render.QuadItemRenderer; |
||||
|
||||
|
||||
public class ItemTwig extends ItemBaseWeapon { |
||||
|
||||
public ItemTwig(ItemModel model) |
||||
{ |
||||
super(model); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected ItemRenderer makeRenderer() |
||||
{ |
||||
return new QuadItemRenderer(this, Res.getTxQuad("item.twig")); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public int getAttackPoints() |
||||
{ |
||||
return 1; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public int getMaxUses() |
||||
{ |
||||
return 10; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public String getVisualName() |
||||
{ |
||||
return "Twig"; |
||||
} |
||||
} |
@ -0,0 +1,22 @@ |
||||
package mightypork.rogue.world.tile; |
||||
|
||||
|
||||
import mightypork.gamecore.util.math.color.Color; |
||||
import mightypork.gamecore.util.math.color.pal.RGB; |
||||
|
||||
|
||||
public class TileColors { |
||||
|
||||
public static final Color NULL = RGB.NONE; |
||||
public static final Color FLOOR = RGB.GRAY_DARK; |
||||
public static final Color WALL = RGB.GRAY_LIGHT; |
||||
public static final Color DOOR = RGB.BROWN; |
||||
public static final Color COLLAPSED_WALL = RGB.GRAY; |
||||
|
||||
public static final Color ENTRANCE = RGB.CYAN; |
||||
public static final Color EXIT = Color.fromHex(0x00EA8C); |
||||
|
||||
public static final Color SECRET_DOOR_REVEALED = RGB.PINK; |
||||
public static final Color SECRET_DOOR_HIDDEN = WALL; |
||||
|
||||
} |
@ -0,0 +1,101 @@ |
||||
package mightypork.rogue.world.tile.impl; |
||||
|
||||
|
||||
import java.io.IOException; |
||||
|
||||
import mightypork.gamecore.util.ion.IonInput; |
||||
import mightypork.gamecore.util.ion.IonOutput; |
||||
import mightypork.rogue.world.tile.TileModel; |
||||
import mightypork.rogue.world.tile.TileType; |
||||
|
||||
|
||||
public abstract class TileBaseChest extends TileWithItems { |
||||
|
||||
public static final double POST_OPEN_DURA = 0.3; |
||||
public boolean opened = false; |
||||
public boolean removed = false; |
||||
public double timeSinceOpen = 10000; |
||||
|
||||
private int clicks = 1; |
||||
|
||||
|
||||
public TileBaseChest(TileModel model) |
||||
{ |
||||
super(model); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public TileType getType() |
||||
{ |
||||
return TileType.FLOOR; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public boolean isWalkable() |
||||
{ |
||||
return removed; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected boolean shouldRenderItems() |
||||
{ |
||||
return removed; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public boolean onClick() |
||||
{ |
||||
if (opened & removed) return false; |
||||
|
||||
if (clicks > 0) { |
||||
clicks--; |
||||
|
||||
if (clicks == 0) { |
||||
opened = true; |
||||
timeSinceOpen = 0; |
||||
getWorld().getConsole().msgOpenChest(); |
||||
} |
||||
|
||||
} else { |
||||
if (opened && !removed && timeSinceOpen > POST_OPEN_DURA) { |
||||
removed = true; |
||||
clicks--; |
||||
} |
||||
} |
||||
|
||||
|
||||
return true; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void save(IonOutput out) throws IOException |
||||
{ |
||||
super.save(out); |
||||
out.writeIntByte(clicks); |
||||
out.writeBoolean(opened); |
||||
out.writeBoolean(removed); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void load(IonInput in) throws IOException |
||||
{ |
||||
super.load(in); |
||||
clicks = in.readIntByte(); |
||||
opened = in.readBoolean(); |
||||
removed = in.readBoolean(); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void updateTile(double delta) |
||||
{ |
||||
super.updateTile(delta); |
||||
if (opened && timeSinceOpen < 10000) timeSinceOpen += delta; |
||||
} |
||||
} |
@ -0,0 +1,25 @@ |
||||
package mightypork.rogue.world.tile.impl.brick; |
||||
|
||||
|
||||
import mightypork.rogue.Res; |
||||
import mightypork.rogue.world.tile.TileModel; |
||||
import mightypork.rogue.world.tile.TileRenderer; |
||||
import mightypork.rogue.world.tile.impl.TileBaseChest; |
||||
import mightypork.rogue.world.tile.render.ChestRenderer; |
||||
|
||||
|
||||
public class TileBrickChest extends TileBaseChest { |
||||
|
||||
public TileBrickChest(TileModel model) |
||||
{ |
||||
super(model); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected TileRenderer makeRenderer() |
||||
{ |
||||
return new ChestRenderer(this, Res.getTxQuad("tile.brick.floor"), Res.getTxQuad("tile.extra.chest.closed"), Res.getTxQuad("tile.extra.chest.open")); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,50 @@ |
||||
package mightypork.rogue.world.tile.render; |
||||
|
||||
|
||||
import mightypork.gamecore.render.Render; |
||||
import mightypork.gamecore.resources.textures.TxQuad; |
||||
import mightypork.rogue.world.level.render.TileRenderContext; |
||||
import mightypork.rogue.world.tile.TileRenderer; |
||||
import mightypork.rogue.world.tile.impl.TileBaseChest; |
||||
|
||||
|
||||
public class ChestRenderer extends TileRenderer { |
||||
|
||||
private final TxQuad txqFloor; |
||||
private final TxQuad txqChest; |
||||
|
||||
private final TileBaseChest chestTile; |
||||
private final TxQuad txqChestOpen; |
||||
|
||||
|
||||
public ChestRenderer(TileBaseChest tile, TxQuad txq, TxQuad chest, TxQuad chestOpen) |
||||
{ |
||||
super(tile); |
||||
|
||||
this.chestTile = tile; |
||||
|
||||
this.txqFloor = txq; |
||||
this.txqChest = chest; |
||||
this.txqChestOpen = chestOpen; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void renderTile(TileRenderContext context) |
||||
{ |
||||
Render.quadTextured(context.getRect(), txqFloor); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void renderExtra(TileRenderContext context) |
||||
{ |
||||
if (!chestTile.opened) { |
||||
Render.quadTextured(context.getRect(), txqChest); |
||||
} else { |
||||
if (!chestTile.removed) { |
||||
Render.quadTextured(context.getRect(), txqChestOpen); |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue