diff --git a/res/img/items.png b/res/img/items.png index 6f18100..71c16ae 100644 Binary files a/res/img/items.png and b/res/img/items.png differ diff --git a/res/img/items.xcf b/res/img/items.xcf index 31a7fdf..d713046 100644 Binary files a/res/img/items.xcf and b/res/img/items.xcf differ diff --git a/res/img/tiles.png b/res/img/tiles.png index f3621ab..c3e14e5 100644 Binary files a/res/img/tiles.png and b/res/img/tiles.png differ diff --git a/res/img/tiles.xcf b/res/img/tiles.xcf index 4c8cf30..68d1d8d 100644 Binary files a/res/img/tiles.xcf and b/res/img/tiles.xcf differ diff --git a/src/mightypork/gamecore/app/BaseApp.java b/src/mightypork/gamecore/app/BaseApp.java index ffab61a..bf50d74 100644 --- a/src/mightypork/gamecore/app/BaseApp.java +++ b/src/mightypork/gamecore/app/BaseApp.java @@ -21,7 +21,7 @@ import mightypork.gamecore.util.annot.DefaultImpl; import mightypork.gamecore.util.files.InstanceLock; import mightypork.gamecore.util.ion.Ion; import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Step; +import mightypork.gamecore.util.math.algo.Move; /** @@ -153,7 +153,7 @@ public abstract class BaseApp implements AppAccess, UncaughtExceptionHandler { protected void registerIonizables() { Ion.registerType(Coord.ION_MARK, Coord.class); - Ion.registerType(Step.ION_MARK, Step.class); + Ion.registerType(Move.ION_MARK, Move.class); } diff --git a/src/mightypork/gamecore/eventbus/EventBus.java b/src/mightypork/gamecore/eventbus/EventBus.java index 988af77..8f55824 100644 --- a/src/mightypork/gamecore/eventbus/EventBus.java +++ b/src/mightypork/gamecore/eventbus/EventBus.java @@ -15,6 +15,7 @@ import mightypork.gamecore.eventbus.event_flags.ImmediateEvent; import mightypork.gamecore.eventbus.event_flags.NotLoggedEvent; import mightypork.gamecore.eventbus.events.Destroyable; import mightypork.gamecore.logging.Log; +import mightypork.gamecore.util.Utils; /** @@ -142,10 +143,6 @@ final public class EventBus implements Destroyable, BusAccess { /** Messages queued for delivery */ private final DelayQueue sendQueue = new DelayQueue<>(); - private volatile boolean sendingDirect = false; - - private BusEvent lastEvt; - /** * Make a new bus and start it's queue thread. @@ -180,13 +177,13 @@ final public class EventBus implements Destroyable, BusAccess { { assertLive(); - final DelayedEvent adelay = event.getClass().getAnnotation(DelayedEvent.class); + final DelayedEvent adelay = Utils.getAnnotation(event, DelayedEvent.class); if (adelay != null) { sendDelayed(event, adelay.delay()); return; } - if (event.getClass().isAnnotationPresent(ImmediateEvent.class)) { + if (Utils.hasAnnotation(event, ImmediateEvent.class)) { sendDirect(event); return; } @@ -364,7 +361,6 @@ final public class EventBus implements Destroyable, BusAccess { for (int i = 0; i < 2; i++) { // two tries. -// channels.setBuffering(true); for (final EventChannel b : channels) { if (b.canBroadcast(event)) { accepted = true; @@ -373,7 +369,6 @@ final public class EventBus implements Destroyable, BusAccess { if (event.isConsumed()) break; } -// channels.setBuffering(false); if (!accepted) if (addChannelForEvent(event)) continue; @@ -388,7 +383,7 @@ final public class EventBus implements Destroyable, BusAccess { private boolean shallLog(BusEvent event) { if (!detailedLogging) return false; - if (event.getClass().isAnnotationPresent(NotLoggedEvent.class)) return false; + if (Utils.hasAnnotation(event, NotLoggedEvent.class)) return false; return true; } diff --git a/src/mightypork/gamecore/util/Utils.java b/src/mightypork/gamecore/util/Utils.java index 49b1c38..f8729e4 100644 --- a/src/mightypork/gamecore/util/Utils.java +++ b/src/mightypork/gamecore/util/Utils.java @@ -1,6 +1,9 @@ package mightypork.gamecore.util; +import java.lang.annotation.Annotation; + + /** * Assorted utils * @@ -14,4 +17,32 @@ public final class Utils { t.start(); return t; } + + + public static boolean hasAnnotation(Object tested, Class annotation) + { + return tested.getClass().isAnnotationPresent(annotation); + } + + + public static T getAnnotation(Object tested, Class annotation) + { + return tested.getClass().getAnnotation(annotation); + } + + + /** + * Pick first non-null option + * + * @param options options + * @return the selected option + */ + public static Object fallback(Object... options) + { + for (final Object o : options) { + if (o != null) return o; + } + + return null; // all null + } } diff --git a/src/mightypork/gamecore/util/error/CorruptDataException.java b/src/mightypork/gamecore/util/error/CorruptDataException.java new file mode 100644 index 0000000..5c1383c --- /dev/null +++ b/src/mightypork/gamecore/util/error/CorruptDataException.java @@ -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); + } + +} diff --git a/src/mightypork/gamecore/util/error/CorruptedDataException.java b/src/mightypork/gamecore/util/error/CorruptedDataException.java deleted file mode 100644 index c026c9b..0000000 --- a/src/mightypork/gamecore/util/error/CorruptedDataException.java +++ /dev/null @@ -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); - } - -} diff --git a/src/mightypork/gamecore/util/error/IllegalValueException.java b/src/mightypork/gamecore/util/error/IllegalValueException.java index 74d03bc..9add26c 100644 --- a/src/mightypork/gamecore/util/error/IllegalValueException.java +++ b/src/mightypork/gamecore/util/error/IllegalValueException.java @@ -1,6 +1,12 @@ package mightypork.gamecore.util.error; +/** + * Thrown when a invalid value is given to a method, or found in a data object / + * file etc + * + * @author MightyPork + */ public class IllegalValueException extends RuntimeException { public IllegalValueException() @@ -25,10 +31,4 @@ public class IllegalValueException extends RuntimeException { super(message, cause); } - - public IllegalValueException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) - { - super(message, cause, enableSuppression, writableStackTrace); - } - } diff --git a/src/mightypork/gamecore/util/error/KeyAlreadyExistsException.java b/src/mightypork/gamecore/util/error/KeyAlreadyExistsException.java index ac8c26c..2cac099 100644 --- a/src/mightypork/gamecore/util/error/KeyAlreadyExistsException.java +++ b/src/mightypork/gamecore/util/error/KeyAlreadyExistsException.java @@ -1,6 +1,11 @@ package mightypork.gamecore.util.error; +/** + * Thrown by a map-like class when the key specified is already taken. + * + * @author MightyPork + */ public class KeyAlreadyExistsException extends RuntimeException { public KeyAlreadyExistsException() diff --git a/src/mightypork/gamecore/util/ion/IonInput.java b/src/mightypork/gamecore/util/ion/IonInput.java index 278259c..c4eef32 100644 --- a/src/mightypork/gamecore/util/ion/IonInput.java +++ b/src/mightypork/gamecore/util/ion/IonInput.java @@ -10,7 +10,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; -import mightypork.gamecore.util.error.CorruptedDataException; +import mightypork.gamecore.util.error.CorruptDataException; /** @@ -360,7 +360,7 @@ public class IonInput { return readStrings(); default: - throw new CorruptedDataException("Invalid mark: " + mark); + throw new CorruptDataException("Invalid mark: " + mark); } } @@ -378,7 +378,7 @@ public class IonInput { if (mark == Ion.ENTRY) return true; if (mark == Ion.END) return false; - throw new CorruptedDataException("Unexpected mark in sequence: " + mark); + throw new CorruptDataException("Unexpected mark in sequence: " + mark); } @@ -411,7 +411,7 @@ public class IonInput { } return filled; } catch (final ClassCastException e) { - throw new CorruptedDataException("Unexpected element type in sequence.", e); + throw new CorruptDataException("Unexpected element type in sequence.", e); } } @@ -448,7 +448,7 @@ public class IonInput { } return filled; } catch (final ClassCastException e) { - throw new CorruptedDataException("Unexpected element type in map.", e); + throw new CorruptDataException("Unexpected element type in map.", e); } } } diff --git a/src/mightypork/gamecore/util/math/Calc.java b/src/mightypork/gamecore/util/math/Calc.java index 718f500..1d40931 100644 --- a/src/mightypork/gamecore/util/math/Calc.java +++ b/src/mightypork/gamecore/util/math/Calc.java @@ -619,6 +619,19 @@ public class Calc { * @return picked element */ public static T pick(List list) + { + return pick(rand, list); + } + + + /** + * Pick random element from a given list. + * + * @param rand RNG + * @param list list of choices + * @return picked element + */ + public static T pick(Random rand, List list) { if (list.size() == 0) return null; return list.get(rand.nextInt(list.size())); @@ -718,4 +731,14 @@ public class Calc { return out; } + + + public static int countBits(byte b) + { + int c = 0; + for (int i = 0; i < 8; i++) { + c += (b >> i) & 1; + } + return c; + } } diff --git a/src/mightypork/gamecore/util/math/Range.java b/src/mightypork/gamecore/util/math/Range.java index 559edde..70318a4 100644 --- a/src/mightypork/gamecore/util/math/Range.java +++ b/src/mightypork/gamecore/util/math/Range.java @@ -1,6 +1,9 @@ package mightypork.gamecore.util.math; +import java.util.Random; + + /** * Numeric range, able to generate random numbers and give min/max values. * @@ -71,7 +74,7 @@ public class Range { */ public int randInt() { - return Calc.randInt(Calc.rand, (int) Math.round(min), (int) Math.round(min)); + return randInt(Calc.rand); } @@ -82,7 +85,31 @@ public class Range { */ public double randDouble() { - return min + Calc.rand.nextDouble() * (max - min); + return randDouble(Calc.rand); + } + + + /** + * Get random integer from range + * + * @param rand RNG + * @return random int + */ + public int randInt(Random rand) + { + return Calc.randInt(rand, (int) Math.round(min), (int) Math.round(min)); + } + + + /** + * Get random double from this range + * + * @param rand RNG + * @return random double + */ + public double randDouble(Random rand) + { + return min + rand.nextDouble() * (max - min); } diff --git a/src/mightypork/gamecore/util/math/algo/Coord.java b/src/mightypork/gamecore/util/math/algo/Coord.java index a09e839..7c53a8b 100644 --- a/src/mightypork/gamecore/util/math/algo/Coord.java +++ b/src/mightypork/gamecore/util/math/algo/Coord.java @@ -87,7 +87,7 @@ public class Coord implements IonObjBundled, IonObjBinary { } - public Coord add(Step added) + public Coord add(Move added) { return add(added.x(), added.y()); } diff --git a/src/mightypork/gamecore/util/math/algo/Step.java b/src/mightypork/gamecore/util/math/algo/Move.java similarity index 80% rename from src/mightypork/gamecore/util/math/algo/Step.java rename to src/mightypork/gamecore/util/math/algo/Move.java index ce20118..d78535b 100644 --- a/src/mightypork/gamecore/util/math/algo/Step.java +++ b/src/mightypork/gamecore/util/math/algo/Move.java @@ -16,18 +16,18 @@ import mightypork.gamecore.util.ion.IonOutput; * * @author MightyPork */ -public class Step implements IonObjBinary, IonObjBundled { +public class Move implements IonObjBinary, IonObjBundled { public static final int ION_MARK = 254; - public static final Step NORTH = new Step(0, -1); - public static final Step SOUTH = new Step(0, 1); - public static final Step EAST = new Step(1, 0); - public static final Step WEST = new Step(-1, 0); - public static final Step NONE = new Step(0, 0); + public static final Move NORTH = new Move(0, -1); + public static final Move SOUTH = new Move(0, 1); + public static final Move EAST = new Move(1, 0); + public static final Move WEST = new Move(-1, 0); + public static final Move NONE = new Move(0, 0); - public static Step make(int x, int y) + public static Move make(int x, int y) { x = x < 0 ? -1 : x > 0 ? 1 : 0; y = y < 0 ? -1 : y > 0 ? 1 : 0; @@ -38,20 +38,20 @@ public class Step implements IonObjBinary, IonObjBundled { if (x == 1 && y == 0) return EAST; if (x == 0 && y == 0) return NONE; - return new Step(x, y); + return new Move(x, y); } private byte x; private byte y; - public Step() + public Move() { // for ion } - public Step(int x, int y) + public Move(int x, int y) { this.x = (byte) (x < 0 ? -1 : x > 0 ? 1 : 0); this.y = (byte) (y < 0 ? -1 : y > 0 ? 1 : 0); diff --git a/src/mightypork/gamecore/util/math/algo/Moves.java b/src/mightypork/gamecore/util/math/algo/Moves.java new file mode 100644 index 0000000..08f1911 --- /dev/null +++ b/src/mightypork/gamecore/util/math/algo/Moves.java @@ -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 ALL_SIDES = Collections.unmodifiableList(Arrays.asList( + NW, + N, + NE, + E, + SE, + S, + SW, + W + )); + + public final static List 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); + } +} diff --git a/src/mightypork/gamecore/util/math/algo/Sides.java b/src/mightypork/gamecore/util/math/algo/Sides.java deleted file mode 100644 index f397c7b..0000000 --- a/src/mightypork/gamecore/util/math/algo/Sides.java +++ /dev/null @@ -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)]; - } -} diff --git a/src/mightypork/gamecore/util/math/algo/floodfill/FloodFill.java b/src/mightypork/gamecore/util/math/algo/floodfill/FloodFill.java index 4539354..e6a84fc 100644 --- a/src/mightypork/gamecore/util/math/algo/floodfill/FloodFill.java +++ b/src/mightypork/gamecore/util/math/algo/floodfill/FloodFill.java @@ -3,10 +3,11 @@ package mightypork.gamecore.util.math.algo.floodfill; import java.util.Collection; import java.util.LinkedList; +import java.util.List; import java.util.Queue; import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Step; +import mightypork.gamecore.util.math.algo.Move; public abstract class FloodFill { @@ -17,7 +18,7 @@ public abstract class FloodFill { public abstract boolean canSpreadFrom(Coord pos); - public abstract Step[] getSpreadSides(); + public abstract List getSpreadSides(); /** @@ -49,7 +50,6 @@ public abstract class FloodFill { activeNodes.add(start); - final Step[] sides = getSpreadSides(); boolean forceSpreadNext = forceSpreadStart(); boolean limitReached = false; @@ -62,7 +62,7 @@ public abstract class FloodFill { forceSpreadNext = false; - for (final Step spr : sides) { + for (final Move spr : getSpreadSides()) { final Coord next = current.add(spr); if (activeNodes.contains(next) || foundNodes.contains(next)) continue; diff --git a/src/mightypork/gamecore/util/math/algo/pathfinding/PathFinder.java b/src/mightypork/gamecore/util/math/algo/pathfinding/PathFinder.java index eb9eb86..8173d06 100644 --- a/src/mightypork/gamecore/util/math/algo/pathfinding/PathFinder.java +++ b/src/mightypork/gamecore/util/math/algo/pathfinding/PathFinder.java @@ -8,7 +8,7 @@ import java.util.LinkedList; import java.util.List; import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Step; +import mightypork.gamecore.util.math.algo.Move; import mightypork.gamecore.util.math.algo.pathfinding.heuristics.DiagonalHeuristic; import mightypork.gamecore.util.math.algo.pathfinding.heuristics.ManhattanHeuristic; @@ -29,24 +29,24 @@ public abstract class PathFinder { private boolean ignoreEnd; - public List findPathRelative(Coord start, Coord end) + public List findPathRelative(Coord start, Coord end) { return findPathRelative(start, end, ignoreStart, ignoreEnd); } - public List findPathRelative(Coord start, Coord end, boolean ignoreStart, boolean ignoreEnd) + public List findPathRelative(Coord start, Coord end, boolean ignoreStart, boolean ignoreEnd) { final List path = findPath(start, end, ignoreStart, ignoreEnd); if (path == null) return null; - final List out = new ArrayList<>(); + final List out = new ArrayList<>(); final Coord current = start.copy(); for (final Coord c : path) { if (c.equals(current)) continue; - out.add(Step.make(c.x - current.x, c.y - current.y)); + out.add(Move.make(c.x - current.x, c.y - current.y)); current.x = c.x; current.y = c.y; } @@ -76,8 +76,6 @@ public abstract class PathFinder { open.add(n); } - final Step[] walkDirs = getWalkSides(); - Node current = null; while (true) { @@ -93,7 +91,7 @@ public abstract class PathFinder { break; } - for (final Step go : walkDirs) { + for (final Move go : getWalkSides()) { final Coord c = current.pos.add(go); if (!isAccessible(c) && !(c.equals(end) && ignoreEnd) && !(c.equals(start) && ignoreStart)) continue; @@ -225,7 +223,7 @@ public abstract class PathFinder { protected abstract Heuristic getHeuristic(); - protected abstract Step[] getWalkSides(); + protected abstract List getWalkSides(); /** diff --git a/src/mightypork/gamecore/util/math/algo/pathfinding/PathFinderProxy.java b/src/mightypork/gamecore/util/math/algo/pathfinding/PathFinderProxy.java index 3e56461..163966b 100644 --- a/src/mightypork/gamecore/util/math/algo/pathfinding/PathFinderProxy.java +++ b/src/mightypork/gamecore/util/math/algo/pathfinding/PathFinderProxy.java @@ -1,8 +1,10 @@ package mightypork.gamecore.util.math.algo.pathfinding; +import java.util.List; + import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Step; +import mightypork.gamecore.util.math.algo.Move; /** @@ -51,7 +53,7 @@ public class PathFinderProxy extends PathFinder { @Override - protected Step[] getWalkSides() + protected List getWalkSides() { return source.getWalkSides(); } diff --git a/src/mightypork/gamecore/util/math/color/pal/COMMODORE.java b/src/mightypork/gamecore/util/math/color/pal/CMDR.java similarity index 96% rename from src/mightypork/gamecore/util/math/color/pal/COMMODORE.java rename to src/mightypork/gamecore/util/math/color/pal/CMDR.java index ffb0166..63a8833 100644 --- a/src/mightypork/gamecore/util/math/color/pal/COMMODORE.java +++ b/src/mightypork/gamecore/util/math/color/pal/CMDR.java @@ -9,7 +9,7 @@ import mightypork.gamecore.util.math.color.Color; * * @author MightyPork */ -public interface COMMODORE { +public interface CMDR { Color BLACK = Color.fromHex(0x040013); Color WHITE = Color.fromHex(0xFFFFFF); diff --git a/src/mightypork/gamecore/util/math/color/pal/RGB.java b/src/mightypork/gamecore/util/math/color/pal/RGB.java index ac81669..cdbdaf5 100644 --- a/src/mightypork/gamecore/util/math/color/pal/RGB.java +++ b/src/mightypork/gamecore/util/math/color/pal/RGB.java @@ -38,6 +38,7 @@ public class RGB { public static final Color PINK = Color.fromHex(0xFF3FFC); public static final Color ORANGE = Color.fromHex(0xFC4800); + public static final Color BROWN = Color.fromHex(0x83501B); public static final Color NONE = Color.rgba(0, 0, 0, 0); } diff --git a/src/mightypork/gamecore/util/objects/ObjectUtils.java b/src/mightypork/gamecore/util/objects/ObjectUtils.java deleted file mode 100644 index 15d5aff..0000000 --- a/src/mightypork/gamecore/util/objects/ObjectUtils.java +++ /dev/null @@ -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 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 List arrayToList(T[] objs) - { - final ArrayList list = new ArrayList<>(); - for (final T o : objs) { - list.add(o); - } - return list; - } -} diff --git a/src/mightypork/gamecore/util/strings/AlphanumComparator.java b/src/mightypork/gamecore/util/strings/AlphanumComparator.java new file mode 100644 index 0000000..7c3d87e --- /dev/null +++ b/src/mightypork/gamecore/util/strings/AlphanumComparator.java @@ -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 { + + 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; + } +} diff --git a/src/mightypork/rogue/GameLoop.java b/src/mightypork/rogue/GameLoop.java index 8ac684a..db88b6f 100644 --- a/src/mightypork/rogue/GameLoop.java +++ b/src/mightypork/rogue/GameLoop.java @@ -50,7 +50,7 @@ public final class GameLoop extends MainLoop implements ActionRequest.Listener { @Override public void execute() { - Res.getEffect("gui.shutter").play(1); + Res.getSoundEffect("gui.shutter").play(1); Utils.runAsThread(new TaskTakeScreenshot()); } }; diff --git a/src/mightypork/rogue/Res.java b/src/mightypork/rogue/Res.java index f146b86..027e726 100644 --- a/src/mightypork/rogue/Res.java +++ b/src/mightypork/rogue/Res.java @@ -60,9 +60,8 @@ public final class Res { fonts.loadFont("tinyutf", font = new DeferredFont("/res/font/TinyUnicode2.ttf", Glyphs.basic, 16)); font.setDiscardRatio(6 / 16D, 2 / 16D); - // aliases based on concrete usage + // aliases fonts.addAlias("thick", "press_start"); - fonts.addAlias("thin", "battlenet"); fonts.addAlias("tiny", "tinyutf"); } @@ -135,6 +134,8 @@ public final class Res { textures.add("tile.brick.passage", grid.makeSheet(3, 2, 4, 1)); textures.add("tile.brick.stairs.up", grid.makeQuad(0, 6)); textures.add("tile.brick.stairs.down", grid.makeQuad(1, 6)); + textures.add("tile.extra.chest.closed", grid.makeQuad(0, 4)); + textures.add("tile.extra.chest.open", grid.makeQuad(1, 4)); // shadows textures.add("tile.shadow.n", grid.makeQuad(0, 7)); @@ -165,12 +166,14 @@ public final class Res { textures.add("item.meat", grid.makeQuad(0, 0)); textures.add("item.club", grid.makeQuad(1, 0)); textures.add("item.sword", grid.makeQuad(2, 0)); - textures.add("item.hammer", grid.makeQuad(3, 0)); + textures.add("item.axe", grid.makeQuad(3, 0)); textures.add("item.stone", grid.makeQuad(4, 0)); textures.add("item.bone", grid.makeQuad(5, 0)); textures.add("item.cheese", grid.makeQuad(6, 0)); textures.add("item.sandwich", grid.makeQuad(7, 0)); textures.add("item.heart_piece", grid.makeQuad(0, 1)); + textures.add("item.knife", grid.makeQuad(1, 1)); + textures.add("item.twig", grid.makeQuad(2, 1)); } @@ -192,7 +195,7 @@ public final class Res { * @param key * @return sheet */ - public static TxSheet txs(String key) + public static TxSheet getTxSheet(String key) { return textures.getSheet(key); } @@ -204,19 +207,19 @@ public final class Res { * @param key * @return quad */ - public static TxQuad txq(String key) + public static TxQuad getTxQuad(String key) { return textures.getQuad(key); } - public static LoopPlayer getLoop(String key) + public static LoopPlayer getSoundLoop(String key) { return sounds.getLoop(key); } - public static EffectPlayer getEffect(String key) + public static EffectPlayer getSoundEffect(String key) { return sounds.getEffect(key); } diff --git a/src/mightypork/rogue/screens/game/HudLayer.java b/src/mightypork/rogue/screens/game/HudLayer.java index 95564ea..46f65e1 100644 --- a/src/mightypork/rogue/screens/game/HudLayer.java +++ b/src/mightypork/rogue/screens/game/HudLayer.java @@ -84,9 +84,9 @@ public class HudLayer extends ScreenLayer { final HeartBar hearts = new HeartBar( playerHealthTotal, playerHealthActive, - Res.txq("hud.heart.on"), - Res.txq("hud.heart.half"), - Res.txq("hud.heart.off"), + Res.getTxQuad("hud.heart.on"), + Res.getTxQuad("hud.heart.half"), + Res.getTxQuad("hud.heart.off"), AlignX.LEFT); //@formatter:on @@ -117,13 +117,13 @@ public class HudLayer extends ScreenLayer { NavButton btn; - nav.addRight(btn = new NavButton(Res.txq("nav.button.fg.inventory"))); + nav.addRight(btn = new NavButton(Res.getTxQuad("nav.button.fg.inventory"))); btn.setAction(gameScreen.actionToggleInv); - nav.addRight(btn = new NavButton(Res.txq("nav.button.fg.eat"))); + nav.addRight(btn = new NavButton(Res.getTxQuad("nav.button.fg.eat"))); btn.setAction(gameScreen.actionEat); - nav.addRight(btn = new NavButton(Res.txq("nav.button.fg.pause"))); + nav.addRight(btn = new NavButton(Res.getTxQuad("nav.button.fg.pause"))); btn.setAction(gameScreen.actionTogglePause); @@ -131,19 +131,19 @@ public class HudLayer extends ScreenLayer { //nav.addLeft(new NavButton(Res.txq("nav.button.fg.options"))); //nav.addLeft(new NavButton(Res.txq("nav.button.fg.help"))); - nav.addLeft(btn = new NavButton(Res.txq("nav.button.fg.menu"))); + nav.addLeft(btn = new NavButton(Res.getTxQuad("nav.button.fg.menu"))); btn.setAction(gameScreen.actionMenu); - nav.addLeft(btn = new NavButton(Res.txq("nav.button.fg.save"))); + nav.addLeft(btn = new NavButton(Res.getTxQuad("nav.button.fg.save"))); btn.setAction(gameScreen.actionSave); - nav.addLeft(btn = new NavButton(Res.txq("nav.button.fg.load"))); + nav.addLeft(btn = new NavButton(Res.getTxQuad("nav.button.fg.load"))); btn.setAction(gameScreen.actionLoad); - nav.addLeft(btn = new NavButton(Res.txq("nav.button.fg.map"))); + nav.addLeft(btn = new NavButton(Res.getTxQuad("nav.button.fg.map"))); btn.setAction(gameScreen.actionToggleMinimap); - nav.addLeft(btn = new NavButton(Res.txq("nav.button.fg.magnify"))); + nav.addLeft(btn = new NavButton(Res.getTxQuad("nav.button.fg.magnify"))); btn.setAction(gameScreen.actionToggleZoom); } diff --git a/src/mightypork/rogue/screens/game/IngameNav.java b/src/mightypork/rogue/screens/game/IngameNav.java index 1626eb3..d512344 100644 --- a/src/mightypork/rogue/screens/game/IngameNav.java +++ b/src/mightypork/rogue/screens/game/IngameNav.java @@ -43,7 +43,7 @@ public class IngameNav extends LayoutComponent { paintHelper = leftEdge().growRight(height().mul(4)); - bg = Res.txq("nav.bg"); + bg = Res.getTxQuad("nav.bg"); } diff --git a/src/mightypork/rogue/screens/game/InvSlot.java b/src/mightypork/rogue/screens/game/InvSlot.java index 8ae5fe2..1002a94 100644 --- a/src/mightypork/rogue/screens/game/InvSlot.java +++ b/src/mightypork/rogue/screens/game/InvSlot.java @@ -50,8 +50,8 @@ public class InvSlot extends ClickableComponent { public InvSlot(int index, InvSlot[] allSlots) { super(); - this.txBase = Res.txq("inv.slot.base"); - this.txSelected = Res.txq("inv.slot.selected"); + this.txBase = Res.getTxQuad("inv.slot.base"); + this.txSelected = Res.getTxQuad("inv.slot.selected"); this.index = index; this.slots = allSlots; diff --git a/src/mightypork/rogue/screens/game/InvLayer.java b/src/mightypork/rogue/screens/game/InventoryLayer.java similarity index 92% rename from src/mightypork/rogue/screens/game/InvLayer.java rename to src/mightypork/rogue/screens/game/InventoryLayer.java index 7926d47..72b17ee 100644 --- a/src/mightypork/rogue/screens/game/InvLayer.java +++ b/src/mightypork/rogue/screens/game/InventoryLayer.java @@ -22,7 +22,7 @@ import mightypork.rogue.world.item.Item; import mightypork.rogue.world.item.ItemType; -public class InvLayer extends ScreenLayer { +public class InventoryLayer extends ScreenLayer { private static final int SLOT_COUNT = 8; private static final int SLOT_ROW = 4; @@ -86,7 +86,7 @@ public class InvLayer extends ScreenLayer { } - public InvLayer(final ScreenGame screen) + public InventoryLayer(final ScreenGame screen) { super(screen); @@ -200,17 +200,7 @@ public class InvLayer extends ScreenLayer { final int selected = getSelectedSlot(); if (selected != -1) { - final PlayerFacade pl = WorldProvider.get().getPlayer(); - final Item itm = pl.getInventory().getItem(selected); - if (itm != null && !itm.isEmpty()) { - - final Item piece = itm.split(1); - if (itm.isEmpty()) pl.getInventory().setItem(selected, null); - - if (!pl.getLevel().getTile(pl.getCoord()).dropItem(piece)) { - pl.getInventory().addItem(piece); // add back - } - } + WorldProvider.get().getPlayer().dropItem(selected); } } }); diff --git a/src/mightypork/rogue/screens/game/NavButton.java b/src/mightypork/rogue/screens/game/NavButton.java index e1c7aed..cd14946 100644 --- a/src/mightypork/rogue/screens/game/NavButton.java +++ b/src/mightypork/rogue/screens/game/NavButton.java @@ -20,9 +20,9 @@ public class NavButton extends ClickableComponent { public NavButton(TxQuad fg) { super(); - this.base = Res.txq("nav.button.bg.base"); - this.hover = Res.txq("nav.button.bg.hover"); - this.down = Res.txq("nav.button.bg.down"); + this.base = Res.getTxQuad("nav.button.bg.base"); + this.hover = Res.getTxQuad("nav.button.bg.hover"); + this.down = Res.getTxQuad("nav.button.bg.down"); this.fg = fg; } diff --git a/src/mightypork/rogue/screens/game/ScreenGame.java b/src/mightypork/rogue/screens/game/ScreenGame.java index 507fe35..6a9e893 100644 --- a/src/mightypork/rogue/screens/game/ScreenGame.java +++ b/src/mightypork/rogue/screens/game/ScreenGame.java @@ -10,7 +10,6 @@ import mightypork.gamecore.gui.screens.LayeredScreen; import mightypork.gamecore.input.KeyStroke; import mightypork.gamecore.input.Keys; import mightypork.gamecore.logging.Log; -import mightypork.gamecore.util.math.Calc; import mightypork.rogue.Config; import mightypork.rogue.GameStateManager.GameState; import mightypork.rogue.events.GameStateRequest; @@ -32,7 +31,7 @@ public class ScreenGame extends LayeredScreen { WORLD, INV; } - private InvLayer invLayer; + private InventoryLayer invLayer; private HudLayer hudLayer; private WorldLayer worldLayer; @@ -131,6 +130,17 @@ public class ScreenGame extends LayeredScreen { } }; + public Action actionDropLastPickedItem = new Action() { + + @Override + public void execute() + { + final PlayerFacade pl = WorldProvider.get().getPlayer(); + if (pl.isDead() || pl.getWorld().isPaused()) return; + pl.dropItem(pl.getInventory().getLastAddIndex()); + } + }; + /** * Set gui state (overlay) @@ -175,7 +185,7 @@ public class ScreenGame extends LayeredScreen { { super(app); - addLayer(invLayer = new InvLayer(this)); + addLayer(invLayer = new InventoryLayer(this)); invLayer.setEnabled(false); invLayer.setVisible(false); @@ -187,29 +197,18 @@ public class ScreenGame extends LayeredScreen { worldLayer.setEnabled(true); worldLayer.setVisible(true); - // TODO temporary, remove - bindKey(new KeyStroke(Keys.N, Keys.MOD_CONTROL), new Runnable() { - - @Override - public void run() - { - WorldProvider.get().createWorld(Calc.rand.nextLong()); - } - }); - //pause key bindKey(new KeyStroke(Keys.P), actionTogglePause); bindKey(new KeyStroke(Keys.PAUSE), actionTogglePause); bindKey(new KeyStroke(Keys.SPACE), actionTogglePause); bindKey(new KeyStroke(Keys.I), actionToggleInv); + bindKey(new KeyStroke(Keys.D), actionDropLastPickedItem); bindKey(new KeyStroke(Keys.E), actionEat); bindKey(new KeyStroke(Keys.M), actionToggleMinimap); bindKey(new KeyStroke(Keys.Z), actionToggleZoom); - bindKey(new KeyStroke(Keys.R, Keys.MOD_CONTROL), actionLoad); bindKey(new KeyStroke(Keys.L, Keys.MOD_CONTROL), actionLoad); - bindKey(new KeyStroke(Keys.S, Keys.MOD_CONTROL), actionSave); // add as actions - enableables. @@ -224,11 +223,12 @@ public class ScreenGame extends LayeredScreen { worldActions.add(actionSave); worldActions.add(actionLoad); worldActions.add(actionMenu); + worldActions.add(actionDropLastPickedItem); worldActions.setEnabled(true); - // TMP TODO remove - bindKey(new KeyStroke(Keys.X), new Runnable() { + // CHEAT - X-ray + bindKey(new KeyStroke(Keys.F10, Keys.MOD_CONTROL), new Runnable() { @Override public void run() diff --git a/src/mightypork/rogue/screens/game/WorldConsoleRenderer.java b/src/mightypork/rogue/screens/game/WorldConsoleRenderer.java index a9e1e1f..b606cdd 100644 --- a/src/mightypork/rogue/screens/game/WorldConsoleRenderer.java +++ b/src/mightypork/rogue/screens/game/WorldConsoleRenderer.java @@ -69,7 +69,7 @@ public class WorldConsoleRenderer extends BaseComponent { } } catch (final ConcurrentModificationException e) { - Log.e(e); // this should not happen anymore + Log.e(e); // this should not happen } diff --git a/src/mightypork/rogue/screens/menu/ScreenMainMenu.java b/src/mightypork/rogue/screens/menu/ScreenMainMenu.java index d2dacd6..bea06b2 100644 --- a/src/mightypork/rogue/screens/menu/ScreenMainMenu.java +++ b/src/mightypork/rogue/screens/menu/ScreenMainMenu.java @@ -64,7 +64,7 @@ public class ScreenMainMenu extends LayeredScreen { root.add(layout); int r = 0; - final ImagePainter ip = new ImagePainter(Res.txq("logo")); + final ImagePainter ip = new ImagePainter(Res.getTxQuad("logo")); ip.keepAspectRatio(); layout.put(ip, r, 0, 4, 1); r += 5; diff --git a/src/mightypork/rogue/screens/select_world/WorldSlot.java b/src/mightypork/rogue/screens/select_world/WorldSlot.java index 765debb..9d62ad2 100644 --- a/src/mightypork/rogue/screens/select_world/WorldSlot.java +++ b/src/mightypork/rogue/screens/select_world/WorldSlot.java @@ -162,6 +162,7 @@ public class WorldSlot extends ConstraintLayout { if (!file.exists()) { label = ""; + worldBundle = null; } else { try { worldBundle = Ion.fromFile(file); @@ -173,7 +174,8 @@ public class WorldSlot extends ConstraintLayout { delBtn.setVisible(true); delBtn.setEnabled(true); - } catch (final IOException e) { + } catch (final Exception e) { + Log.w("Error loading world save.", e); label = ""; } } diff --git a/src/mightypork/rogue/world/Inventory.java b/src/mightypork/rogue/world/Inventory.java index a5e8586..4f21302 100644 --- a/src/mightypork/rogue/world/Inventory.java +++ b/src/mightypork/rogue/world/Inventory.java @@ -14,6 +14,7 @@ public class Inventory implements IonObjBinary { public static final short ION_MARK = 54; private Item[] items; + private int lastAddIndex = 0; public Inventory(int size) @@ -87,6 +88,8 @@ public class Inventory implements IonObjBinary { */ public Item getItem(int i) { + if (i < 0 || i > getSize()) return null; + verifyIndex(i); final Item itm = items[i]; if (itm == null || itm.isEmpty()) return null; @@ -112,6 +115,7 @@ public class Inventory implements IonObjBinary { { verifyIndex(i); items[i] = item; + lastAddIndex = i; } @@ -136,7 +140,10 @@ public class Inventory implements IonObjBinary { for (int i = 0; i < getSize(); i++) { final Item itm = getItem(i); if (itm != null) { - if (itm.addItem(stored)) return true; + if (itm.addItem(stored)) { + lastAddIndex = i; + return true; + } } } @@ -145,6 +152,7 @@ public class Inventory implements IonObjBinary { final Item itm = getItem(i); if (itm == null) { setItem(i, stored.split(stored.getAmount())); // store a copy, empty the original item. + lastAddIndex = i; return true; } } @@ -167,6 +175,12 @@ public class Inventory implements IonObjBinary { } + public int getLastAddIndex() + { + return lastAddIndex; + } + + @Override public String toString() { diff --git a/src/mightypork/rogue/world/PlayerControl.java b/src/mightypork/rogue/world/PlayerControl.java index 56c0791..9a72397 100644 --- a/src/mightypork/rogue/world/PlayerControl.java +++ b/src/mightypork/rogue/world/PlayerControl.java @@ -5,7 +5,7 @@ import java.util.HashSet; import java.util.Set; import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Step; +import mightypork.gamecore.util.math.algo.Move; import mightypork.gamecore.util.math.constraints.vect.Vect; import mightypork.rogue.world.entity.Entity; import mightypork.rogue.world.entity.EntityType; @@ -50,25 +50,25 @@ public abstract class PlayerControl { public void goNorth() { - go(Step.NORTH); + go(Move.NORTH); } public void goSouth() { - go(Step.SOUTH); + go(Move.SOUTH); } public void goEast() { - go(Step.EAST); + go(Move.EAST); } public void goWest() { - go(Step.WEST); + go(Move.WEST); } @@ -85,7 +85,7 @@ public abstract class PlayerControl { } - public boolean canGo(Step side) + public boolean canGo(Move side) { return getPlayer().canGoTo(side); } @@ -97,7 +97,7 @@ public abstract class PlayerControl { * @param side * @return */ - public boolean clickTile(Step side) + public boolean clickTile(Move side) { return doClickTile(getPlayer().getCoord().add(side).toVect()); } @@ -132,14 +132,14 @@ public abstract class PlayerControl { } - public void go(Step side) + public void go(Move side) { getPlayer().cancelPath(); getPlayer().addPathStep(side); } - public boolean tryGo(Step e) + public boolean tryGo(Move e) { if (!canGo(e)) return false; go(e); diff --git a/src/mightypork/rogue/world/PlayerFacade.java b/src/mightypork/rogue/world/PlayerFacade.java index 85bc7d9..7c48313 100644 --- a/src/mightypork/rogue/world/PlayerFacade.java +++ b/src/mightypork/rogue/world/PlayerFacade.java @@ -7,7 +7,7 @@ import java.util.Comparator; import java.util.List; import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Step; +import mightypork.gamecore.util.math.algo.Move; import mightypork.gamecore.util.math.constraints.vect.Vect; import mightypork.rogue.world.entity.Entity; import mightypork.rogue.world.item.Item; @@ -158,7 +158,7 @@ public class PlayerFacade { } - public void addPathStep(Step step) + public void addPathStep(Move step) { world.playerEntity.pos.addStep(step); } @@ -400,8 +400,32 @@ public class PlayerFacade { } - public boolean canGoTo(Step side) + public boolean canGoTo(Move side) { return getEntity().pos.canGoTo(side); } + + + public void dropItem(int itemIndex) + { + final Item itm = getInventory().getItem(itemIndex); + if (itm != null && !itm.isEmpty()) { + + final Item piece = itm.split(1); + getInventory().clean(); + + Coord dropPos; + if (world.playerEntity.pos.isMoving()) { + dropPos = world.playerEntity.pos.getLastPos(); + } else { + dropPos = getCoord(); + } + + if (!getLevel().getTile(dropPos).dropItem(piece)) { + getInventory().addItem(piece); // add back + } else { + world.getConsole().msgDroppedItem(piece); + } + } + } } diff --git a/src/mightypork/rogue/world/WorldConsole.java b/src/mightypork/rogue/world/WorldConsole.java index 17e01d3..73903a2 100644 --- a/src/mightypork/rogue/world/WorldConsole.java +++ b/src/mightypork/rogue/world/WorldConsole.java @@ -129,7 +129,7 @@ public class WorldConsole implements Updateable { public void msgDie(Entity attacker) { - addMessage("You've been defeated by a " + attacker.getVisualName() + "!"); + addMessage("You've been defeated by " + addArticle(attacker.getVisualName()) + "!"); } @@ -141,7 +141,7 @@ public class WorldConsole implements Updateable { public void msgEat(Item item) { - addMessage("You've eaten a " + item.getVisualName() + "."); + addMessage("You've eaten " + addArticle(item.getVisualName()) + "."); } @@ -153,7 +153,7 @@ public class WorldConsole implements Updateable { public void msgEquipWeapon(Item item) { - addMessage("You're now wielding " + (item == null ? "NOTHING" : "a " + item.getVisualName()) + "."); + addMessage("You're now wielding " + (item == null ? "NOTHING" : addArticle(item.getVisualName())) + "."); } @@ -165,7 +165,7 @@ public class WorldConsole implements Updateable { public void msgKill(Entity prey) { - addMessage("You've killed a " + prey.getVisualName() + "."); + addMessage("You've killed " + addArticle(prey.getVisualName()) + "."); } @@ -183,12 +183,19 @@ public class WorldConsole implements Updateable { public void msgPick(Item item) { - addMessage("You've picked up a " + item.getVisualName() + "."); + addMessage("You've picked up " + addArticle(item.getVisualName()) + "."); lastPickupItem = item; timeSinceLastPickup = 0; } + public void msgDroppedItem(Item item) + { + addMessage("You've dropped " + addArticle(item.getVisualName()) + "."); + lastPickupItem = null; + } + + public void msgWeaponBreak(Item item) { addMessage("Your " + item.getVisualName() + " has broken!"); @@ -217,4 +224,26 @@ public class WorldConsole implements Updateable { { addMessage("Error while loading; See the log for details."); } + + + public void msgOpenChest() + { + addMessage("You've opened a treasure chest!"); + } + + + private String addArticle(String name) + { + switch (Character.toLowerCase(name.charAt(0))) { + case 'a': + case 'e': + case 'i': + case 'o': + case 'u': + case 'y': + return "an " + name; + default: + return "a " + name; + } + } } diff --git a/src/mightypork/rogue/world/entity/EntityPathFinder.java b/src/mightypork/rogue/world/entity/EntityPathFinder.java index 03e238c..af456c4 100644 --- a/src/mightypork/rogue/world/entity/EntityPathFinder.java +++ b/src/mightypork/rogue/world/entity/EntityPathFinder.java @@ -1,9 +1,11 @@ package mightypork.rogue.world.entity; +import java.util.List; + import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Sides; -import mightypork.gamecore.util.math.algo.Step; +import mightypork.gamecore.util.math.algo.Move; +import mightypork.gamecore.util.math.algo.Moves; import mightypork.gamecore.util.math.algo.pathfinding.Heuristic; import mightypork.gamecore.util.math.algo.pathfinding.PathFinder; @@ -53,9 +55,9 @@ public class EntityPathFinder extends PathFinder { @Override - public Step[] getWalkSides() + public List getWalkSides() { - return Sides.CARDINAL_SIDES; + return Moves.CARDINAL_SIDES; } } diff --git a/src/mightypork/rogue/world/entity/impl/BossRatAi.java b/src/mightypork/rogue/world/entity/impl/BossRatAi.java index fc1fb54..8b54ba2 100644 --- a/src/mightypork/rogue/world/entity/impl/BossRatAi.java +++ b/src/mightypork/rogue/world/entity/impl/BossRatAi.java @@ -22,14 +22,14 @@ public class BossRatAi extends GrayRatAi { { super(entity); - setAttackTime(0.7); + setAttackTime(0.2); } @Override protected int getAttackStrength() { - return Calc.randInt(5, 11); + return Calc.randInt(1, 6); } @@ -52,6 +52,6 @@ public class BossRatAi extends GrayRatAi { @Override protected double getStepTime() { - return isIdle() ? 0.6 : 0.4; + return isIdle() ? 0.6 : 0.37; } } diff --git a/src/mightypork/rogue/world/entity/impl/MonsterAi.java b/src/mightypork/rogue/world/entity/impl/MonsterAi.java index 133c102..27d6402 100644 --- a/src/mightypork/rogue/world/entity/impl/MonsterAi.java +++ b/src/mightypork/rogue/world/entity/impl/MonsterAi.java @@ -8,8 +8,8 @@ import mightypork.gamecore.util.annot.DefaultImpl; import mightypork.gamecore.util.ion.IonBundle; import mightypork.gamecore.util.math.Calc; import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Sides; -import mightypork.gamecore.util.math.algo.Step; +import mightypork.gamecore.util.math.algo.Move; +import mightypork.gamecore.util.math.algo.Moves; import mightypork.gamecore.util.math.algo.pathfinding.PathFinder; import mightypork.gamecore.util.math.algo.pathfinding.PathFinderProxy; import mightypork.rogue.world.entity.AiTimer; @@ -65,7 +65,7 @@ public class MonsterAi extends EntityModule implements EntityMoveListener { if (entity.pos.isMoving()) return; if (Calc.rand.nextInt(10) == 0) { - entity.pos.addStep(Sides.randomCardinal()); + entity.pos.addStep(Moves.randomCardinal()); } } }; @@ -260,7 +260,7 @@ public class MonsterAi extends EntityModule implements EntityMoveListener { } - private List getPathToPrey(Entity prey) + private List getPathToPrey(Entity prey) { if (!isPreyValid(prey)) return null; @@ -280,7 +280,7 @@ public class MonsterAi extends EntityModule implements EntityMoveListener { return; } - final List preyPath = getPathToPrey(prey); + final List preyPath = getPathToPrey(prey); if (preyPath == null || preyPath.size() > getPreyAbandonDistance()) { stopChasing(); diff --git a/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java b/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java index 7be52f3..1b396e5 100644 --- a/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java +++ b/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java @@ -10,7 +10,7 @@ import java.util.Set; import mightypork.gamecore.util.ion.IonBundle; import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Step; +import mightypork.gamecore.util.math.algo.Move; import mightypork.gamecore.util.math.constraints.vect.VectConst; import mightypork.rogue.world.entity.Entity; import mightypork.rogue.world.entity.EntityModule; @@ -22,7 +22,7 @@ public class EntityModulePosition extends EntityModule { private final Coord lastPos = new Coord(0, 0); private boolean walking = false; - private final Queue path = new LinkedList<>(); + private final Queue path = new LinkedList<>(); private final EntityPos entityPos = new EntityPos(); private double stepTime = 0.5; @@ -136,7 +136,7 @@ public class EntityModulePosition extends EntityModule { walking = true; - final Step step = path.poll(); + final Move step = path.poll(); final Coord planned = entityPos.getCoord().add(step.toCoord()); @@ -177,7 +177,7 @@ public class EntityModulePosition extends EntityModule { * * @param step */ - public void addStep(Step step) + public void addStep(Move step) { if (path.isEmpty() && !canGoTo(step)) return; @@ -203,7 +203,7 @@ public class EntityModulePosition extends EntityModule { public boolean navigateTo(Coord target) { if (target.equals(getCoord())) return true; - final List newPath = entity.getPathFinder().findPathRelative(entityPos.getCoord(), target); + final List newPath = entity.getPathFinder().findPathRelative(entityPos.getCoord(), target); if (newPath == null) return false; cancelPath(); @@ -228,7 +228,7 @@ public class EntityModulePosition extends EntityModule { * * @param path steps */ - public void addSteps(List path) + public void addSteps(List path) { this.path.addAll(path); } @@ -284,9 +284,15 @@ public class EntityModulePosition extends EntityModule { } - public boolean canGoTo(Step side) + public boolean canGoTo(Move side) { return entity.getPathFinder().isAccessible(getCoord().add(side)); } + + public Coord getLastPos() + { + return lastPos; + } + } diff --git a/src/mightypork/rogue/world/entity/modules/EntityPos.java b/src/mightypork/rogue/world/entity/modules/EntityPos.java index 78c95ce..140cbf9 100644 --- a/src/mightypork/rogue/world/entity/modules/EntityPos.java +++ b/src/mightypork/rogue/world/entity/modules/EntityPos.java @@ -8,7 +8,7 @@ import mightypork.gamecore.util.ion.IonBundle; import mightypork.gamecore.util.ion.IonObjBundled; import mightypork.gamecore.util.math.Easing; import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Step; +import mightypork.gamecore.util.math.algo.Move; import mightypork.gamecore.util.math.constraints.vect.Vect; import mightypork.gamecore.util.math.constraints.vect.VectConst; import mightypork.gamecore.util.math.constraints.vect.mutable.VectAnimated; @@ -128,7 +128,7 @@ class EntityPos implements IonObjBundled, Updateable { } - public void walk(Step step, double secs) + public void walk(Move step, double secs) { setTo(coord.x + step.x(), coord.y + step.y()); walkOffset.setTo(-step.x(), -step.y()); diff --git a/src/mightypork/rogue/world/entity/render/EntityRendererMobLR.java b/src/mightypork/rogue/world/entity/render/EntityRendererMobLR.java index b26884e..8c3d5bb 100644 --- a/src/mightypork/rogue/world/entity/render/EntityRendererMobLR.java +++ b/src/mightypork/rogue/world/entity/render/EntityRendererMobLR.java @@ -37,7 +37,7 @@ public class EntityRendererMobLR extends EntityRenderer { public EntityRendererMobLR(Entity entity, String sheetKey) { this.entity = entity; - this.sheet = Res.txs(sheetKey); + this.sheet = Res.getTxSheet(sheetKey); } diff --git a/src/mightypork/rogue/world/gen/LevelBuilder.java b/src/mightypork/rogue/world/gen/LevelBuilder.java new file mode 100644 index 0000000..00c51e7 --- /dev/null +++ b/src/mightypork/rogue/world/gen/LevelBuilder.java @@ -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 roomsFirst = new LinkedList<>(); + private final LinkedList roomsMiddle = new LinkedList<>(); + private final LinkedList roomsLast = new LinkedList<>(); + + private final LinkedList items = new LinkedList<>(); + private final LinkedList 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 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 list) + { + while (!list.isEmpty()) { + + Collections.shuffle(list, rand); + + for (final Iterator 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.
+ * 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)); + } + +} diff --git a/src/mightypork/rogue/world/gen/LevelGenerator.java b/src/mightypork/rogue/world/gen/LevelGenerator.java deleted file mode 100644 index 81b3bec..0000000 --- a/src/mightypork/rogue/world/gen/LevelGenerator.java +++ /dev/null @@ -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; - } -} diff --git a/src/mightypork/rogue/world/gen/MapTheme.java b/src/mightypork/rogue/world/gen/MapTheme.java index d4be91c..22fbf0b 100644 --- a/src/mightypork/rogue/world/gen/MapTheme.java +++ b/src/mightypork/rogue/world/gen/MapTheme.java @@ -30,4 +30,7 @@ public interface MapTheme { TileModel exit(); + + + TileModel chest(); } diff --git a/src/mightypork/rogue/world/gen/RoomBuilder.java b/src/mightypork/rogue/world/gen/RoomBuilder.java index 39c3e4d..7da8a82 100644 --- a/src/mightypork/rogue/world/gen/RoomBuilder.java +++ b/src/mightypork/rogue/world/gen/RoomBuilder.java @@ -13,5 +13,5 @@ import mightypork.gamecore.util.math.algo.Coord; */ public interface RoomBuilder { - RoomDesc buildToFit(ScratchMap map, MapTheme theme, Random rand, Coord center) throws WorldGenError; + RoomEntry buildRoom(ScratchMap map, MapTheme theme, Random rand, Coord center) throws WorldGenError; } diff --git a/src/mightypork/rogue/world/gen/RoomDesc.java b/src/mightypork/rogue/world/gen/RoomEntry.java similarity index 88% rename from src/mightypork/rogue/world/gen/RoomDesc.java rename to src/mightypork/rogue/world/gen/RoomEntry.java index e3dc346..56a43fc 100644 --- a/src/mightypork/rogue/world/gen/RoomDesc.java +++ b/src/mightypork/rogue/world/gen/RoomEntry.java @@ -5,17 +5,17 @@ import mightypork.gamecore.util.math.algo.Coord; /** - * Room description + * Room description entry for {@link ScratchMap} * * @author MightyPork */ -public class RoomDesc { +public class RoomEntry { final Coord min; final Coord max; - public RoomDesc(Coord min, Coord max) + public RoomEntry(Coord min, Coord max) { super(); this.min = min; diff --git a/src/mightypork/rogue/world/gen/Rooms.java b/src/mightypork/rogue/world/gen/Rooms.java new file mode 100644 index 0000000..86a399a --- /dev/null +++ b/src/mightypork/rogue/world/gen/Rooms.java @@ -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); + } +} diff --git a/src/mightypork/rogue/world/gen/ScratchMap.java b/src/mightypork/rogue/world/gen/ScratchMap.java index 733781e..0d96027 100644 --- a/src/mightypork/rogue/world/gen/ScratchMap.java +++ b/src/mightypork/rogue/world/gen/ScratchMap.java @@ -10,8 +10,8 @@ import java.util.Set; import mightypork.gamecore.logging.Log; import mightypork.gamecore.util.math.Calc; import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Sides; -import mightypork.gamecore.util.math.algo.Step; +import mightypork.gamecore.util.math.algo.Move; +import mightypork.gamecore.util.math.algo.Moves; import mightypork.gamecore.util.math.algo.pathfinding.Heuristic; import mightypork.gamecore.util.math.algo.pathfinding.PathFinder; import mightypork.rogue.world.entity.Entity; @@ -33,7 +33,7 @@ public class ScratchMap { private final int width; private final int height; - private final List rooms = new ArrayList<>(); + private final List rooms = new ArrayList<>(); /** Coords to connect with corridors */ private final List nodes = new ArrayList<>(); @@ -96,9 +96,9 @@ public class ScratchMap { @Override - public Step[] getWalkSides() + public List getWalkSides() { - return Sides.CARDINAL_SIDES; + return Moves.CARDINAL_SIDES; } }; @@ -136,83 +136,99 @@ public class ScratchMap { } - public boolean addRoom(RoomBuilder rb, boolean critical) + public void addRoom(RoomBuilder rb, boolean critical) throws WorldGenError { - final Coord center = Coord.make(0, 0); - - int failed = 0; - - int failed_total = 0; - - while (true) { + try { + if (rooms.size() > 0) minimizeBounds(); - final int sizeX = genMax.x - genMin.x; - final int sizeY = genMax.y - genMin.y; + final Coord roomPos = Coord.make(0, 0); - center.x = genMin.x + rand.nextInt(sizeX); - center.y = genMin.y + rand.nextInt(sizeY); + int failed = 0; + int failed_total = 0; - switch (rand.nextInt(4)) { - case 0: - center.x += (failed_total / 35); - break; - case 1: - center.x -= (failed_total / 35); - break; - case 2: - center.y += (failed_total / 35); - break; - case 3: - center.y -= (failed_total / 35); - } - - final RoomDesc rd = rb.buildToFit(this, theme, rand, center); - if (rd != null) { - rooms.add(rd); - - genMin.x = Math.min(genMin.x, rd.min.x); - genMin.y = Math.min(genMin.y, rd.min.y); + while (true) { - genMax.x = Math.max(genMax.x, rd.max.x); - genMax.y = Math.max(genMax.y, rd.max.y); - clampBounds(); + final int sizeX = genMax.x - genMin.x; + final int sizeY = genMax.y - genMin.y; - nodes.add(center); -// Log.f3("Placed room (failed " + failed_total + " x)."); + roomPos.x = genMin.x + rand.nextInt(sizeX + 1); + roomPos.y = genMin.y + rand.nextInt(sizeY + 1); - return true; - } else { - failed++; - failed_total++; - - if (failed_total > 1000) { - return false; + switch (rand.nextInt(4)) { + case 0: + roomPos.x += (failed_total / 35); + break; + case 1: + roomPos.x -= (failed_total / 35); + break; + case 2: + roomPos.y += (failed_total / 35); + break; + case 3: + roomPos.y -= (failed_total / 35); } - if (failed > 300) { - Log.w("Faild to build room."); - if (critical) { - - genMin.x -= 5; - genMin.y -= 5; - genMax.x += 5; - genMax.y += 5; - clampBounds(); - - failed = 0; - Log.f3("Trying again."); - continue; - - } else { - return false; + final RoomEntry rd = rb.buildRoom(this, theme, rand, roomPos); + if (rd != null) { + + rooms.add(rd); + + genMin.x = Math.min(genMin.x, rd.min.x); + genMin.y = Math.min(genMin.y, rd.min.y); + + genMax.x = Math.max(genMax.x, rd.max.x); + genMax.y = Math.max(genMax.y, rd.max.y); + clampBounds(); + + nodes.add(roomPos); + + return; + + } else { + failed++; + failed_total++; + + if (failed_total > 1000) { + throw new WorldGenError("Failed to add a room."); + } + + if (failed > 300) { + Log.w("Faild to build room."); + if (critical) { + + // expand gen bounds + genMin.x -= 5; + genMin.y -= 5; + genMax.x += 5; + genMax.y += 5; + + clampBounds(); + + failed = 0; + Log.f3("Trying again."); + continue; + + } else { + throw new WorldGenError("Failed to add a room."); + } } } } + } catch (final WorldGenError e) { + if (!critical) { + Log.w("Could not place a room.", e); + return; + } else { + // rethrow + throw e; + } } - } + /** + * Clamp bounds to available area + */ private void clampBounds() { genMin.x = Calc.clamp(genMin.x, 0, width - 1); @@ -222,6 +238,27 @@ public class ScratchMap { } + /** + * Minimize gen bounds based on defined room bounds + */ + private void minimizeBounds() + { + final Coord low = Coord.make(width, height); + final Coord high = Coord.make(0, 0); + + for (final RoomEntry rd : rooms) { + low.x = Math.min(low.x, rd.min.x); + low.y = Math.min(low.y, rd.min.y); + + high.x = Math.max(high.x, rd.max.x); + high.y = Math.max(high.y, rd.max.y); + } + + genMin.setTo(low); + genMax.setTo(high); + } + + public boolean isIn(Coord pos) { return pos.x >= 0 && pos.x < width && pos.y >= 0 && pos.y < height; @@ -258,7 +295,7 @@ public class ScratchMap { public boolean isClear(Coord min, Coord max) { if (!isIn(min) || !isIn(max)) return false; - for (final RoomDesc r : rooms) { + for (final RoomEntry r : rooms) { if (r.intersectsWith(min, max)) return false; } @@ -266,6 +303,12 @@ public class ScratchMap { } + public void protect(Coord pos, TileProtectLevel prot) + { + protect(pos, pos, prot); + } + + public void protect(Coord min, Coord max, TileProtectLevel prot) { if (!isIn(min) || !isIn(max)) throw new WorldGenError("Tile(s) not in map: " + min + " , " + max); @@ -327,7 +370,7 @@ public class ScratchMap { } } starts.add(start); - start = Calc.pick(nodes); + start = Calc.pick(rand, nodes); } } @@ -377,31 +420,24 @@ public class ScratchMap { } + /** + * @return dimensions of the area taken by non-null tiles + */ public Coord getNeededSize() { return Coord.make(genMax.x - genMin.x + 1, genMax.y - genMin.y + 1); } - public int countBits(byte b) - { - int c = 0; - for (int i = 0; i < 8; i++) { - c += (b >> i) & 1; - } - return c; - } - - public byte findWalls(Coord pos) { byte walls = 0; for (int i = 0; i < 8; i++) { - final Coord cc = pos.add(Sides.get(i)); + final Coord cc = pos.add(Moves.getSide(i)); if (!isIn(cc)) continue; if (getTile(cc).isWall()) { - walls |= Sides.bit(i); + walls |= Moves.getBit(i); } } return walls; @@ -412,11 +448,11 @@ public class ScratchMap { { byte floors = 0; for (int i = 0; i <= 7; i++) { - final Coord cc = pos.add(Sides.get(i)); + final Coord cc = pos.add(Moves.getSide(i)); if (!isIn(cc)) continue; if (getTile(cc).isFloor()) { - floors |= Sides.bit(i); + floors |= Moves.getBit(i); } } return floors; @@ -427,11 +463,11 @@ public class ScratchMap { { byte doors = 0; for (int i = 0; i <= 7; i++) { - final Coord cc = pos.add(Sides.get(i)); + final Coord cc = pos.add(Moves.getSide(i)); if (!isIn(cc)) continue; if (getTile(cc).isDoor()) { - doors |= Sides.bit(i); + doors |= Moves.getBit(i); } } return doors; @@ -442,105 +478,129 @@ public class ScratchMap { { byte nils = 0; for (int i = 0; i <= 7; i++) { - final Coord cc = pos.add(Sides.get(i)); + final Coord cc = pos.add(Moves.getSide(i)); if (!isIn(cc) || getTile(cc).isNull()) { - nils |= Sides.bit(i); + nils |= Moves.getBit(i); } } return nils; } - public void writeToLevel(Level level) + /** + * Fix generator glitches and reduce size to the actual used size + */ + public void fixGlitches() { - if (level.getWorld() == null) { - throw new WorldGenError("Level has no world assigned."); // need for entities - } + final Tile[][] out = new Tile[height][width]; - // make sure no walkable are at edges. - final Coord c = Coord.make(0, 0); - final Coord c1 = Coord.make(0, 0); + // bounds will be adjusted by the actual tiles in the map + genMin.x = width; + genMin.y = height; + genMax.x = 0; + genMax.y = 0; - if (FIX_GLITCHES) { - - final Tile[][] out = new Tile[height][width]; - - for (c.x = 0; c.x < width; c.x++) { - for (c.y = 0; c.y < height; c.y++) { - - final Tile t = getTile(c); - final boolean isNull = t.isNull(); - - final boolean isDoor = !isNull && t.isDoor(); - final boolean isFloor = !isNull && t.isFloor(); - final boolean isWall = !isNull && t.isWall(); + final Coord c = Coord.make(0, 0); + for (c.x = 0; c.x < width; c.x++) { + for (c.y = 0; c.y < height; c.y++) { + + final Tile t = getTile(c); + final boolean isNull = t.isNull(); + + final boolean isDoor = !isNull && t.isDoor(); + final boolean isFloor = !isNull && t.isFloor(); + final boolean isWall = !isNull && t.isWall(); + + // bitmasks + final byte walls = findWalls(c); + final byte nils = findNils(c); + final byte floors = findFloors(c); + + boolean toWall = false; + boolean toFloor = false; + boolean toNull = false; + + do { + if (isWall && floors == 0) { + toNull = true; + break; + } - // bitmasks - final byte walls = findWalls(c); - final byte nils = findNils(c); - final byte floors = findFloors(c); + if (isFloor && (nils & Moves.BITS_CARDINAL) != 0) { + toWall = true; // floor with adjacent cardinal null + break; + } - boolean toWall = false; - boolean toFloor = false; - boolean toNull = false; + if (isNull && (floors & Moves.BITS_DIAGONAL) != 0) { + toWall = true; // null with adjacent diagonal floor + break; + } - do { - if (isWall && floors == 0) { - toNull = true; + if (isDoor) { + + if (Calc.countBits((byte) (floors & Moves.BITS_CARDINAL)) < 2) { + toWall = true; break; } - if (isFloor && (nils & Sides.MASK_CARDINAL) != 0) { - toWall = true; // floor with adjacent cardinal null + if (Calc.countBits((byte) (walls & Moves.BITS_CARDINAL)) > 2) { + toWall = true; break; } - if (isNull && (floors & Sides.MASK_DIAGONAL) != 0) { - toWall = true; // null with adjacent diagonal floor + if (Calc.countBits((byte) (floors & Moves.BITS_CARDINAL)) > 2) { + toFloor = true; break; } - if (isDoor) { - - if (countBits((byte) (floors & Sides.MASK_CARDINAL)) < 2) { - toWall = true; - break; - } - - if (countBits((byte) (walls & Sides.MASK_CARDINAL)) > 2) { - toWall = true; - break; - } - - if (countBits((byte) (floors & Sides.MASK_CARDINAL)) > 2) { - toFloor = true; - break; - } - - if ((floors & Sides.NW_CORNER) == Sides.NW_CORNER) toWall = true; - if ((floors & Sides.NE_CORNER) == Sides.NE_CORNER) toWall = true; - if ((floors & Sides.SW_CORNER) == Sides.SW_CORNER) toWall = true; - if ((floors & Sides.SE_CORNER) == Sides.SE_CORNER) toWall = true; - - } - } while (false); - - if (toNull) { - out[c.y][c.x] = Tiles.NULL.createTile(); - } else if (toWall) { - out[c.y][c.x] = theme.wall().createTile(); - } else if (toFloor) { - out[c.y][c.x] = theme.floor().createTile(); - } else { - out[c.y][c.x] = map[c.y][c.x]; + if ((floors & Moves.BITS_NW_CORNER) == Moves.BITS_NW_CORNER) toWall = true; + if ((floors & Moves.BITS_NE_CORNER) == Moves.BITS_NE_CORNER) toWall = true; + if ((floors & Moves.BITS_SW_CORNER) == Moves.BITS_SW_CORNER) toWall = true; + if ((floors & Moves.BITS_SE_CORNER) == Moves.BITS_SE_CORNER) toWall = true; + } + } while (false); + + if (toNull) { + out[c.y][c.x] = Tiles.NULL.createTile(); + } else if (toWall) { + out[c.y][c.x] = theme.wall().createTile(); + } else if (toFloor) { + out[c.y][c.x] = theme.floor().createTile(); + } else { + out[c.y][c.x] = map[c.y][c.x]; + } + + if (!out[c.y][c.x].isNull()) { + genMin.x = Math.min(genMin.x, c.x); + genMin.y = Math.min(genMin.y, c.y); + + genMax.x = Math.max(genMax.x, c.x); + genMax.y = Math.max(genMax.y, c.y); } } - - map = out; } + map = out; + } + + + /** + * Write tiles and entities into a level + * + * @param level the level + */ + public void writeToLevel(Level level) + { + if (level.getWorld() == null) { + throw new WorldGenError("Level has no world assigned."); // need for entities + } + + // make sure no walkable are at edges. + final Coord c = Coord.make(0, 0); + final Coord c1 = Coord.make(0, 0); + for (c.x = genMin.x, c1.x = 0; c.x <= genMax.x; c.x++, c1.x++) { for (c.y = genMin.y, c1.y = 0; c.y <= genMax.y; c.y++, c1.y++) { level.setTile(c1, getTile(c)); @@ -582,60 +642,74 @@ public class ScratchMap { } - public boolean putItem(Item item, Coord pos) + public boolean addItem(Item item, Coord pos) + { + return addItem(item, pos, true); + } + + + public boolean addItem(Item item, Coord pos, boolean canStack) { if (!isIn(pos)) return false; final Tile t = getTile(pos); + if (!canStack && t.hasItem()) return false; if (t.dropItem(item)) return true; return false; } - public boolean putItemInArea(Item item, Coord min, Coord max, int tries) + public boolean addItemInArea(Item item, Coord min, Coord max, int tries) { final Coord pos = Coord.zero(); - for (int i = 0; i < tries; i++) { - pos.x = min.x + rand.nextInt(max.x - min.x); - pos.y = min.y + rand.nextInt(max.y - min.y); - if (putItem(item, pos)) return true; + for (int i = 0; i < tries / 2; i++) { + pos.x = Calc.randInt(rand, min.x, max.x); + pos.y = Calc.randInt(rand, min.y, max.y); + if (addItem(item, pos, false)) return true; + } + + for (int i = 0; i < tries - (tries / 2); i++) { + pos.x = Calc.randInt(rand, min.x, max.x); + pos.y = Calc.randInt(rand, min.y, max.y); + if (addItem(item, pos, true)) return true; } return false; } - public boolean putItemInMap(Item item, int tries) + public boolean addItemInMap(Item item, int tries) { - return putItemInArea(item, genMin, genMax, tries); + Log.f3("gen bounds: " + genMin + " -> " + genMax); + return addItemInArea(item, genMin, genMax, tries); } - public boolean putEntityInArea(Entity entity, Coord min, Coord max, int tries) + public boolean addEntityInArea(Entity entity, Coord min, Coord max, int tries) { final Coord pos = Coord.zero(); for (int i = 0; i < tries; i++) { - pos.x = min.x + rand.nextInt(max.x - min.x); - pos.y = min.y + rand.nextInt(max.y - min.y); + pos.x = Calc.randInt(rand, min.x, max.x); + pos.y = Calc.randInt(rand, min.y, max.y); if (!isIn(pos)) continue; - if (putEntity(entity, pos)) return true; + if (addEntity(entity, pos)) return true; } return false; } - public boolean putEntityInMap(Entity entity, int tries) + public boolean addEntityInMap(Entity entity, int tries) { - return putEntityInArea(entity, genMin, genMax, tries); + return addEntityInArea(entity, genMin, genMax, tries); } - public boolean putEntity(Entity entity, Coord pos) + public boolean addEntity(Entity entity, Coord pos) { if (!isIn(pos)) return false; diff --git a/src/mightypork/rogue/world/gen/WorldCreator.java b/src/mightypork/rogue/world/gen/WorldCreator.java index 9b2f0b8..dfac5cd 100644 --- a/src/mightypork/rogue/world/gen/WorldCreator.java +++ b/src/mightypork/rogue/world/gen/WorldCreator.java @@ -1,9 +1,21 @@ package mightypork.rogue.world.gen; +import java.util.ArrayList; +import java.util.List; import java.util.Random; +import mightypork.gamecore.logging.Log; +import mightypork.gamecore.util.math.Calc; +import mightypork.gamecore.util.math.Range; import mightypork.rogue.world.World; +import mightypork.rogue.world.entity.Entities; +import mightypork.rogue.world.entity.Entity; +import mightypork.rogue.world.gen.LevelBuilder.BuildOrder; +import mightypork.rogue.world.gen.themes.ThemeBrick; +import mightypork.rogue.world.item.Item; +import mightypork.rogue.world.item.ItemModel; +import mightypork.rogue.world.item.Items; public class WorldCreator { @@ -15,20 +27,127 @@ public class WorldCreator { { synchronized (rand) { rand.setSeed(seed); + final MapTheme theme = new ThemeBrick(); final World w = new World(); w.setSeed(seed); - final int count = 7; + final LevelBuilder levelBuilders[] = new LevelBuilder[7]; - for (int lvl = 1; lvl <= count; lvl++) { - w.addLevel(LevelGenerator.build(w, rand.nextLong(), lvl, LevelGenerator.DUNGEON_THEME, lvl == count)); + // build the level rooms + for (int floor = 1; floor <= 7; floor++) { + final LevelBuilder lb = prepareFloor(rand.nextLong(), floor, theme, floor == 7); + + levelBuilders[floor - 1] = lb; } + + final List weaponsBasic = new ArrayList<>(); + weaponsBasic.add(Items.ROCK); + weaponsBasic.add(Items.BONE); + weaponsBasic.add(Items.TWIG); + + + final List weaponsMedium = new ArrayList<>(); + weaponsMedium.add(Items.CLUB); + + + final List weaponsGood = new ArrayList<>(); + weaponsGood.add(Items.AXE); + weaponsGood.add(Items.SWORD); + weaponsBasic.add(Items.KNIFE); + + + for (int i = 0; i < Calc.randInt(rand, 10, 15); i++) { + final Item item = Calc.pick(rand, weaponsBasic).createItemDamaged(50); + final LevelBuilder lb = levelBuilders[-1 + Calc.randInt(1, 7)]; + lb.addItem(item, false); + } + + + for (int i = 0; i < Calc.randInt(rand, 1, 3); i++) { + final Item item = Calc.pick(rand, weaponsMedium).createItemDamaged(60); + final LevelBuilder lb = levelBuilders[-1 + Calc.randInt(1, 3)]; + lb.addItem(item, false); + } + + + for (int i = 0; i < Calc.randInt(rand, 2, 3); i++) { + final Item item = Calc.pick(rand, weaponsGood).createItemDamaged(60); + final LevelBuilder lb = levelBuilders[-1 + Calc.randInt(3, 7)]; + + lb.addRoom(Rooms.treasure(item), BuildOrder.MIDDLE, true); + } + + + // place random foods + final List randomFood = new ArrayList<>(); + randomFood.add(Items.CHEESE); + randomFood.add(Items.MEAT); + + for (int level = 1; level <= 7; level++) { + + final LevelBuilder lb = levelBuilders[level - 1]; + final Range amount = Range.make(1, level); + + for (int i = 0; i < amount.randInt(rand); i++) { + lb.addItem(Calc.pick(rand, randomFood).createItem(), false); + } + } + + + // place monsters + for (int level = 1; level <= 7; level++) { + + final LevelBuilder lb = levelBuilders[level - 1]; + + final Range amount = Range.make(2 + level * 2, 5 + level * 3.5); + + for (int i = 0; i < amount.randInt(rand); i++) { + Entity e; + + if (level > 2 && rand.nextInt(7 - level + 1) == 0) { + e = Entities.RAT_BROWN.createEntity(); + } else { + e = Entities.RAT_GRAY.createEntity(); + } + + lb.addEntity(e, false); + } + } + + + // compile levels + for (final LevelBuilder lb : levelBuilders) { + w.addLevel(lb.build(w)); + } + + w.createPlayer(); return w; } } + + public static LevelBuilder prepareFloor(long seed, int floor, MapTheme theme, boolean lastLevel) throws WorldGenError + { + Log.f3("Generating level: " + floor); + + final LevelBuilder lb = new LevelBuilder(128, theme, seed); + + lb.addRoom(Rooms.ENTRANCE, BuildOrder.FIRST, true); + + lb.addRoom(Rooms.BASIC, Range.make(1 + floor, 1 + floor * 1.5), BuildOrder.MIDDLE, false); + lb.addRoom(Rooms.DEAD_END, Range.make(0, 1 + floor * 0.6), BuildOrder.MIDDLE, false); + lb.addRoom(Rooms.STORAGE, Range.make(1, Math.ceil(floor / 2D)), BuildOrder.MIDDLE, false); + + if (lastLevel) lb.addRoom(Rooms.BOSS, BuildOrder.LAST, true); + if (!lastLevel) lb.addRoom(Rooms.EXIT, BuildOrder.LAST, true); + + final RoomBuilder heartRoom = Rooms.shrine(Items.HEART_PIECE.createItem()); + lb.addRoom(heartRoom, BuildOrder.LAST, true); + + return lb; + } } diff --git a/src/mightypork/rogue/world/gen/rooms/AbstractRectRoom.java b/src/mightypork/rogue/world/gen/rooms/AbstractRectRoom.java index acebd14..04caaa2 100644 --- a/src/mightypork/rogue/world/gen/rooms/AbstractRectRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/AbstractRectRoom.java @@ -5,10 +5,10 @@ import java.util.Random; import mightypork.gamecore.util.annot.DefaultImpl; import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Sides; +import mightypork.gamecore.util.math.algo.Moves; import mightypork.rogue.world.gen.MapTheme; import mightypork.rogue.world.gen.RoomBuilder; -import mightypork.rogue.world.gen.RoomDesc; +import mightypork.rogue.world.gen.RoomEntry; import mightypork.rogue.world.gen.ScratchMap; import mightypork.rogue.world.gen.TileProtectLevel; import mightypork.rogue.world.tile.TileModel; @@ -17,7 +17,7 @@ import mightypork.rogue.world.tile.TileModel; public abstract class AbstractRectRoom implements RoomBuilder { @Override - public RoomDesc buildToFit(ScratchMap map, MapTheme theme, Random rand, Coord center) + public RoomEntry buildRoom(ScratchMap map, MapTheme theme, Random rand, Coord center) { // half width, half height actually final Coord innerSize = getInnerSize(rand); @@ -42,7 +42,7 @@ public abstract class AbstractRectRoom implements RoomBuilder { buildExtras(map, theme, rand, min, max); - return new RoomDesc(min.add(-1, -1), max); + return new RoomEntry(min.add(-1, -1), max); } @@ -84,7 +84,7 @@ public abstract class AbstractRectRoom implements RoomBuilder { break; } - if ((map.findDoors(door) & Sides.MASK_CARDINAL) == 0) { + if ((map.findDoors(door) & Moves.BITS_CARDINAL) == 0) { map.set(door, getDoorType(theme, rand)); i++; // increment pointer } diff --git a/src/mightypork/rogue/world/gen/rooms/BossRoom.java b/src/mightypork/rogue/world/gen/rooms/BossRoom.java index f948d78..97108a6 100644 --- a/src/mightypork/rogue/world/gen/rooms/BossRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/BossRoom.java @@ -3,7 +3,6 @@ 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.entity.Entities; import mightypork.rogue.world.entity.Entity; @@ -17,21 +16,42 @@ public class BossRoom extends SecretRoom { @Override protected int getDoorCount(Random rand) { - return Calc.randInt(rand, 1, 3); + return 1; } @Override protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max) { + final Coord bossPos = min.add(3, 3); + final Entity boss = Entities.RAT_BOSS.createEntity(); - if (!map.putEntityInArea(boss, min, max, 100)) { - - // just place it anywhere then - if (!map.putEntityInMap(boss, 100)) { - throw new WorldGenError("Could not place boss."); - } - + if (!map.addEntity(boss, bossPos)) { + throw new WorldGenError("Could not place boss."); } + + Entity rat; + + // 4 guardian rats + + rat = Entities.RAT_BROWN.createEntity(); + map.addEntity(rat, min.add(1, 1)); + + rat = Entities.RAT_BROWN.createEntity(); + map.addEntity(rat, Coord.make(max.x - 1, min.y + 1)); + + rat = Entities.RAT_BROWN.createEntity(); + map.addEntity(rat, max.add(-1, -1)); + + rat = Entities.RAT_BROWN.createEntity(); + map.addEntity(rat, Coord.make(min.x + 1, max.y - 1)); + + } + + + @Override + protected Coord getInnerSize(Random rand) + { + return Coord.make(5, 5); } } diff --git a/src/mightypork/rogue/world/gen/rooms/DeadEndRoom.java b/src/mightypork/rogue/world/gen/rooms/DeadEndRoom.java index 2d8a52d..17a00fe 100644 --- a/src/mightypork/rogue/world/gen/rooms/DeadEndRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/DeadEndRoom.java @@ -6,14 +6,14 @@ import java.util.Random; import mightypork.gamecore.util.math.algo.Coord; import mightypork.rogue.world.gen.MapTheme; import mightypork.rogue.world.gen.RoomBuilder; -import mightypork.rogue.world.gen.RoomDesc; +import mightypork.rogue.world.gen.RoomEntry; import mightypork.rogue.world.gen.ScratchMap; public class DeadEndRoom implements RoomBuilder { @Override - public RoomDesc buildToFit(ScratchMap map, MapTheme theme, Random rand, Coord center) + public RoomEntry buildRoom(ScratchMap map, MapTheme theme, Random rand, Coord center) { final Coord low = center.add(-1, -1); final Coord high = center; @@ -21,6 +21,6 @@ public class DeadEndRoom implements RoomBuilder { map.set(center, theme.floor()); - return new RoomDesc(low, high); + return new RoomEntry(low, high); } } diff --git a/src/mightypork/rogue/world/gen/rooms/HeartPieceRoom.java b/src/mightypork/rogue/world/gen/rooms/ItemShrineRoom.java similarity index 61% rename from src/mightypork/rogue/world/gen/rooms/HeartPieceRoom.java rename to src/mightypork/rogue/world/gen/rooms/ItemShrineRoom.java index 543ad58..51fa884 100644 --- a/src/mightypork/rogue/world/gen/rooms/HeartPieceRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/ItemShrineRoom.java @@ -9,30 +9,33 @@ import mightypork.rogue.world.gen.MapTheme; import mightypork.rogue.world.gen.ScratchMap; import mightypork.rogue.world.gen.WorldGenError; import mightypork.rogue.world.item.Item; -import mightypork.rogue.world.item.Items; -public class HeartPieceRoom extends SecretRoom { +public class ItemShrineRoom extends SecretRoom { + + private final Item item; + + + public ItemShrineRoom(Item item) + { + this.item = item; + } + @Override protected int getDoorCount(Random rand) { - return Calc.randInt(rand, 1, 3); + return Calc.randInt(rand, 1, 4); } @Override protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max) { - final Item heart = Items.HEART_PIECE.createItem(); + final Coord center = min.add(2, 2); - if (!map.putItem(heart, min.add(2, 2))) { - if (!map.putItemInArea(heart, min, max, 100)) { - if (!map.putItemInMap(heart, 100)) { - throw new WorldGenError("Could not place heart piece."); - } - - } + if (!map.addItem(item, center)) { + throw new WorldGenError("Could not place item in chest."); } } diff --git a/src/mightypork/rogue/world/gen/rooms/Rooms.java b/src/mightypork/rogue/world/gen/rooms/Rooms.java deleted file mode 100644 index b718b19..0000000 --- a/src/mightypork/rogue/world/gen/rooms/Rooms.java +++ /dev/null @@ -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(); -} diff --git a/src/mightypork/rogue/world/gen/rooms/StorageRoom.java b/src/mightypork/rogue/world/gen/rooms/StorageRoom.java new file mode 100644 index 0000000..d040e8f --- /dev/null +++ b/src/mightypork/rogue/world/gen/rooms/StorageRoom.java @@ -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; + } + } +} diff --git a/src/mightypork/rogue/world/gen/rooms/TreasureChestRoom.java b/src/mightypork/rogue/world/gen/rooms/TreasureChestRoom.java new file mode 100644 index 0000000..0e46f57 --- /dev/null +++ b/src/mightypork/rogue/world/gen/rooms/TreasureChestRoom.java @@ -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); + } +} diff --git a/src/mightypork/rogue/world/gen/rooms/TreasureRoom.java b/src/mightypork/rogue/world/gen/rooms/TreasureRoom.java deleted file mode 100644 index 49875b0..0000000 --- a/src/mightypork/rogue/world/gen/rooms/TreasureRoom.java +++ /dev/null @@ -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); - } - } -} diff --git a/src/mightypork/rogue/world/gen/themes/ThemeBrick.java b/src/mightypork/rogue/world/gen/themes/ThemeBrick.java index 830ff67..b9535ca 100644 --- a/src/mightypork/rogue/world/gen/themes/ThemeBrick.java +++ b/src/mightypork/rogue/world/gen/themes/ThemeBrick.java @@ -56,4 +56,11 @@ public class ThemeBrick implements MapTheme { { return Tiles.BRICK_EXIT; } + + + @Override + public TileModel chest() + { + return Tiles.BRICK_CHEST; + } } diff --git a/src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java b/src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java index 61921f6..fa7e3bb 100644 --- a/src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java +++ b/src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java @@ -6,8 +6,8 @@ import mightypork.gamecore.input.InputSystem; import mightypork.gamecore.input.Keys; import mightypork.gamecore.input.events.KeyEvent; import mightypork.gamecore.input.events.KeyListener; -import mightypork.gamecore.util.math.algo.Sides; -import mightypork.gamecore.util.math.algo.Step; +import mightypork.gamecore.util.math.algo.Move; +import mightypork.gamecore.util.math.algo.Moves; import mightypork.gamecore.util.math.constraints.vect.Vect; import mightypork.rogue.world.entity.impl.PlayerEntity; import mightypork.rogue.world.events.PlayerStepEndListener; @@ -17,7 +17,7 @@ import mightypork.rogue.world.gui.MapView; public class MIPKeyboard extends MapInteractionPlugin implements PlayerStepEndListener, KeyListener, Updateable { private static final int[] keys = { Keys.LEFT, Keys.RIGHT, Keys.UP, Keys.DOWN }; - private static final Step[] sides = { Sides.W, Sides.E, Sides.N, Sides.S }; + private static final Move[] sides = { Moves.W, Moves.E, Moves.N, Moves.S }; public MIPKeyboard(MapView mapView) @@ -72,7 +72,7 @@ public class MIPKeyboard extends MapInteractionPlugin implements PlayerStepEndLi for (int i = 0; i < 4; i++) { if (InputSystem.isKeyDown(keys[i])) { - final Step side = sides[i]; + final Move side = sides[i]; if (mapView.plc.canGo(side)) { mapView.plc.go(side); return true; diff --git a/src/mightypork/rogue/world/gui/interaction/MIPMouse.java b/src/mightypork/rogue/world/gui/interaction/MIPMouse.java index 72084c3..a7a704d 100644 --- a/src/mightypork/rogue/world/gui/interaction/MIPMouse.java +++ b/src/mightypork/rogue/world/gui/interaction/MIPMouse.java @@ -6,7 +6,7 @@ import mightypork.gamecore.input.InputSystem; import mightypork.gamecore.util.math.Calc.Deg; import mightypork.gamecore.util.math.Polar; import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Sides; +import mightypork.gamecore.util.math.algo.Moves; import mightypork.gamecore.util.math.constraints.vect.Vect; import mightypork.rogue.world.entity.impl.PlayerEntity; import mightypork.rogue.world.events.PlayerStepEndListener; @@ -97,16 +97,16 @@ public class MIPMouse extends MapInteractionPlugin implements PlayerStepEndListe switch (dir) { case 0: - return mapView.plc.tryGo(Sides.E); + return mapView.plc.tryGo(Moves.E); case 1: - return mapView.plc.tryGo(Sides.S); + return mapView.plc.tryGo(Moves.S); case 2: - return mapView.plc.tryGo(Sides.W); + return mapView.plc.tryGo(Moves.W); case 3: - return mapView.plc.tryGo(Sides.N); + return mapView.plc.tryGo(Moves.N); } return false; diff --git a/src/mightypork/rogue/world/item/Items.java b/src/mightypork/rogue/world/item/Items.java index cade8e7..66197d8 100644 --- a/src/mightypork/rogue/world/item/Items.java +++ b/src/mightypork/rogue/world/item/Items.java @@ -10,11 +10,7 @@ import mightypork.rogue.world.item.impl.active.ItemHeartPiece; import mightypork.rogue.world.item.impl.food.ItemCheese; import mightypork.rogue.world.item.impl.food.ItemMeat; import mightypork.rogue.world.item.impl.food.ItemSandwich; -import mightypork.rogue.world.item.impl.weapons.ItemBone; -import mightypork.rogue.world.item.impl.weapons.ItemClub; -import mightypork.rogue.world.item.impl.weapons.ItemHammer; -import mightypork.rogue.world.item.impl.weapons.ItemStone; -import mightypork.rogue.world.item.impl.weapons.ItemSword; +import mightypork.rogue.world.item.impl.weapons.*; /** @@ -31,10 +27,12 @@ public final class Items { public static final ItemModel BONE = new ItemModel(3, ItemBone.class); public static final ItemModel SANDWICH = new ItemModel(4, ItemSandwich.class); public static final ItemModel CLUB = new ItemModel(5, ItemClub.class); - public static final ItemModel HAMMER = new ItemModel(6, ItemHammer.class); + public static final ItemModel AXE = new ItemModel(6, ItemAxe.class); public static final ItemModel SWORD = new ItemModel(7, ItemSword.class); - public static final ItemModel ROCK = new ItemModel(8, ItemStone.class); + public static final ItemModel ROCK = new ItemModel(8, ItemRock.class); public static final ItemModel HEART_PIECE = new ItemModel(9, ItemHeartPiece.class); + public static final ItemModel TWIG = new ItemModel(10, ItemTwig.class); + public static final ItemModel KNIFE = new ItemModel(11, ItemKnife.class); public static void register(int id, ItemModel model) diff --git a/src/mightypork/rogue/world/item/impl/active/ItemHeartPiece.java b/src/mightypork/rogue/world/item/impl/active/ItemHeartPiece.java index 243e161..364d887 100644 --- a/src/mightypork/rogue/world/item/impl/active/ItemHeartPiece.java +++ b/src/mightypork/rogue/world/item/impl/active/ItemHeartPiece.java @@ -21,7 +21,7 @@ public class ItemHeartPiece extends Item { @Override protected ItemRenderer makeRenderer() { - return new QuadItemRenderer(this, Res.txq("item.heart_piece")); + return new QuadItemRenderer(this, Res.getTxQuad("item.heart_piece")); } diff --git a/src/mightypork/rogue/world/item/impl/food/ItemCheese.java b/src/mightypork/rogue/world/item/impl/food/ItemCheese.java index b93cb92..9cadd62 100644 --- a/src/mightypork/rogue/world/item/impl/food/ItemCheese.java +++ b/src/mightypork/rogue/world/item/impl/food/ItemCheese.java @@ -19,7 +19,7 @@ public class ItemCheese extends ItemBaseFood { @Override protected ItemRenderer makeRenderer() { - return new QuadItemRenderer(this, Res.txq("item.cheese")); + return new QuadItemRenderer(this, Res.getTxQuad("item.cheese")); } diff --git a/src/mightypork/rogue/world/item/impl/food/ItemMeat.java b/src/mightypork/rogue/world/item/impl/food/ItemMeat.java index ff52066..f3359f8 100644 --- a/src/mightypork/rogue/world/item/impl/food/ItemMeat.java +++ b/src/mightypork/rogue/world/item/impl/food/ItemMeat.java @@ -19,7 +19,7 @@ public class ItemMeat extends ItemBaseFood { @Override protected ItemRenderer makeRenderer() { - return new QuadItemRenderer(this, Res.txq("item.meat")); + return new QuadItemRenderer(this, Res.getTxQuad("item.meat")); } diff --git a/src/mightypork/rogue/world/item/impl/food/ItemSandwich.java b/src/mightypork/rogue/world/item/impl/food/ItemSandwich.java index 1cf185c..940b7d8 100644 --- a/src/mightypork/rogue/world/item/impl/food/ItemSandwich.java +++ b/src/mightypork/rogue/world/item/impl/food/ItemSandwich.java @@ -19,7 +19,7 @@ public class ItemSandwich extends ItemBaseFood { @Override protected ItemRenderer makeRenderer() { - return new QuadItemRenderer(this, Res.txq("item.sandwich")); + return new QuadItemRenderer(this, Res.getTxQuad("item.sandwich")); } diff --git a/src/mightypork/rogue/world/item/impl/weapons/ItemHammer.java b/src/mightypork/rogue/world/item/impl/weapons/ItemAxe.java similarity index 75% rename from src/mightypork/rogue/world/item/impl/weapons/ItemHammer.java rename to src/mightypork/rogue/world/item/impl/weapons/ItemAxe.java index d727d7b..f337b5c 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemHammer.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemAxe.java @@ -8,9 +8,9 @@ import mightypork.rogue.world.item.impl.ItemBaseWeapon; import mightypork.rogue.world.item.render.QuadItemRenderer; -public class ItemHammer extends ItemBaseWeapon { +public class ItemAxe extends ItemBaseWeapon { - public ItemHammer(ItemModel model) + public ItemAxe(ItemModel model) { super(model); } @@ -19,7 +19,7 @@ public class ItemHammer extends ItemBaseWeapon { @Override protected ItemRenderer makeRenderer() { - return new QuadItemRenderer(this, Res.txq("item.hammer")); + return new QuadItemRenderer(this, Res.getTxQuad("item.axe")); } @@ -33,13 +33,13 @@ public class ItemHammer extends ItemBaseWeapon { @Override public int getMaxUses() { - return 100; + return 70; } @Override public String getVisualName() { - return "Hammer"; + return "Axe"; } } diff --git a/src/mightypork/rogue/world/item/impl/weapons/ItemBone.java b/src/mightypork/rogue/world/item/impl/weapons/ItemBone.java index 566e3e9..ffe9631 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemBone.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemBone.java @@ -19,7 +19,7 @@ public class ItemBone extends ItemBaseWeapon { @Override protected ItemRenderer makeRenderer() { - return new QuadItemRenderer(this, Res.txq("item.bone")); + return new QuadItemRenderer(this, Res.getTxQuad("item.bone")); } diff --git a/src/mightypork/rogue/world/item/impl/weapons/ItemClub.java b/src/mightypork/rogue/world/item/impl/weapons/ItemClub.java index 088867f..877cd51 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemClub.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemClub.java @@ -19,7 +19,7 @@ public class ItemClub extends ItemBaseWeapon { @Override protected ItemRenderer makeRenderer() { - return new QuadItemRenderer(this, Res.txq("item.club")); + return new QuadItemRenderer(this, Res.getTxQuad("item.club")); } diff --git a/src/mightypork/rogue/world/item/impl/weapons/ItemKnife.java b/src/mightypork/rogue/world/item/impl/weapons/ItemKnife.java new file mode 100644 index 0000000..ee4fe3b --- /dev/null +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemKnife.java @@ -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"; + } +} diff --git a/src/mightypork/rogue/world/item/impl/weapons/ItemStone.java b/src/mightypork/rogue/world/item/impl/weapons/ItemRock.java similarity index 79% rename from src/mightypork/rogue/world/item/impl/weapons/ItemStone.java rename to src/mightypork/rogue/world/item/impl/weapons/ItemRock.java index 05ddabf..150c20b 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemStone.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemRock.java @@ -8,9 +8,9 @@ import mightypork.rogue.world.item.impl.ItemBaseWeapon; import mightypork.rogue.world.item.render.QuadItemRenderer; -public class ItemStone extends ItemBaseWeapon { +public class ItemRock extends ItemBaseWeapon { - public ItemStone(ItemModel model) + public ItemRock(ItemModel model) { super(model); } @@ -19,7 +19,7 @@ public class ItemStone extends ItemBaseWeapon { @Override protected ItemRenderer makeRenderer() { - return new QuadItemRenderer(this, Res.txq("item.stone")); + return new QuadItemRenderer(this, Res.getTxQuad("item.stone")); } diff --git a/src/mightypork/rogue/world/item/impl/weapons/ItemSword.java b/src/mightypork/rogue/world/item/impl/weapons/ItemSword.java index 513dd8d..0fd8d39 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemSword.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemSword.java @@ -19,14 +19,14 @@ public class ItemSword extends ItemBaseWeapon { @Override protected ItemRenderer makeRenderer() { - return new QuadItemRenderer(this, Res.txq("item.sword")); + return new QuadItemRenderer(this, Res.getTxQuad("item.sword")); } @Override public int getAttackPoints() { - return 6; + return 5; } diff --git a/src/mightypork/rogue/world/item/impl/weapons/ItemTwig.java b/src/mightypork/rogue/world/item/impl/weapons/ItemTwig.java new file mode 100644 index 0000000..d77e85e --- /dev/null +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemTwig.java @@ -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"; + } +} diff --git a/src/mightypork/rogue/world/level/Level.java b/src/mightypork/rogue/world/level/Level.java index e4a11a2..21e3e9e 100644 --- a/src/mightypork/rogue/world/level/Level.java +++ b/src/mightypork/rogue/world/level/Level.java @@ -16,8 +16,8 @@ import mightypork.gamecore.util.ion.IonObjBinary; import mightypork.gamecore.util.ion.IonOutput; import mightypork.gamecore.util.math.Calc; import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Sides; -import mightypork.gamecore.util.math.algo.Step; +import mightypork.gamecore.util.math.algo.Move; +import mightypork.gamecore.util.math.algo.Moves; import mightypork.gamecore.util.math.algo.floodfill.FloodFill; import mightypork.gamecore.util.math.constraints.vect.Vect; import mightypork.gamecore.util.math.noise.NoiseGen; @@ -63,9 +63,9 @@ public class Level implements BusAccess, Updateable, DelegatingClient, Toggleabl private final FloodFill exploreFiller = new FloodFill() { @Override - public Step[] getSpreadSides() + public List getSpreadSides() { - return Sides.ALL_SIDES; + return Moves.ALL_SIDES; } diff --git a/src/mightypork/rogue/world/level/render/TileRenderContext.java b/src/mightypork/rogue/world/level/render/TileRenderContext.java index 1101310..0072355 100644 --- a/src/mightypork/rogue/world/level/render/TileRenderContext.java +++ b/src/mightypork/rogue/world/level/render/TileRenderContext.java @@ -2,7 +2,7 @@ package mightypork.rogue.world.level.render; import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Step; +import mightypork.gamecore.util.math.algo.Move; import mightypork.gamecore.util.math.constraints.rect.Rect; import mightypork.gamecore.util.math.constraints.rect.proxy.RectBound; import mightypork.gamecore.util.math.noise.NoiseGen; @@ -46,7 +46,7 @@ public final class TileRenderContext extends MapRenderContext implements RectBou * @param offset offsets * @return the tile at that position */ - public Tile getAdjacentTile(Step offset) + public Tile getAdjacentTile(Move offset) { return map.getTile(pos.add(offset)); } diff --git a/src/mightypork/rogue/world/tile/Tile.java b/src/mightypork/rogue/world/tile/Tile.java index 03d7606..f2197f7 100644 --- a/src/mightypork/rogue/world/tile/Tile.java +++ b/src/mightypork/rogue/world/tile/Tile.java @@ -98,6 +98,8 @@ public abstract class Tile implements BusAccess, IonObjBlob { @DefaultImpl public void renderExtra(TileRenderContext context) { + initRenderer(); + renderer.renderExtra(context); } diff --git a/src/mightypork/rogue/world/tile/TileColors.java b/src/mightypork/rogue/world/tile/TileColors.java new file mode 100644 index 0000000..0ba6a27 --- /dev/null +++ b/src/mightypork/rogue/world/tile/TileColors.java @@ -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; + +} diff --git a/src/mightypork/rogue/world/tile/TileRenderer.java b/src/mightypork/rogue/world/tile/TileRenderer.java index 8834b6c..690226a 100644 --- a/src/mightypork/rogue/world/tile/TileRenderer.java +++ b/src/mightypork/rogue/world/tile/TileRenderer.java @@ -4,7 +4,8 @@ package mightypork.rogue.world.tile; import mightypork.gamecore.eventbus.events.Updateable; import mightypork.gamecore.render.Render; import mightypork.gamecore.resources.textures.TxQuad; -import mightypork.gamecore.util.math.algo.Sides; +import mightypork.gamecore.util.annot.DefaultImpl; +import mightypork.gamecore.util.math.algo.Moves; import mightypork.gamecore.util.math.constraints.rect.Rect; import mightypork.rogue.Res; import mightypork.rogue.world.level.render.TileRenderContext; @@ -44,24 +45,24 @@ public abstract class TileRenderer implements Updateable { this.tile = tile; if (!inited) { - SH_N = Res.txq("tile.shadow.n"); - SH_S = Res.txq("tile.shadow.s"); - SH_E = Res.txq("tile.shadow.e"); - SH_W = Res.txq("tile.shadow.w"); - SH_NW = Res.txq("tile.shadow.nw"); - SH_NE = Res.txq("tile.shadow.ne"); - SH_SW = Res.txq("tile.shadow.sw"); - SH_SE = Res.txq("tile.shadow.se"); + SH_N = Res.getTxQuad("tile.shadow.n"); + SH_S = Res.getTxQuad("tile.shadow.s"); + SH_E = Res.getTxQuad("tile.shadow.e"); + SH_W = Res.getTxQuad("tile.shadow.w"); + SH_NW = Res.getTxQuad("tile.shadow.nw"); + SH_NE = Res.getTxQuad("tile.shadow.ne"); + SH_SW = Res.getTxQuad("tile.shadow.sw"); + SH_SE = Res.getTxQuad("tile.shadow.se"); - UFOG_N = Res.txq("tile.ufog.n"); - UFOG_S = Res.txq("tile.ufog.s"); - UFOG_E = Res.txq("tile.ufog.e"); - UFOG_W = Res.txq("tile.ufog.w"); - UFOG_NW = Res.txq("tile.ufog.nw"); - UFOG_NE = Res.txq("tile.ufog.ne"); - UFOG_SW = Res.txq("tile.ufog.sw"); - UFOG_SE = Res.txq("tile.ufog.se"); - UFOG_FULL = Res.txq("tile.ufog.full"); + UFOG_N = Res.getTxQuad("tile.ufog.n"); + UFOG_S = Res.getTxQuad("tile.ufog.s"); + UFOG_E = Res.getTxQuad("tile.ufog.e"); + UFOG_W = Res.getTxQuad("tile.ufog.w"); + UFOG_NW = Res.getTxQuad("tile.ufog.nw"); + UFOG_NE = Res.getTxQuad("tile.ufog.ne"); + UFOG_SW = Res.getTxQuad("tile.ufog.sw"); + UFOG_SE = Res.getTxQuad("tile.ufog.se"); + UFOG_FULL = Res.getTxQuad("tile.ufog.full"); inited = true; } } @@ -78,9 +79,9 @@ public abstract class TileRenderer implements Updateable { shadows = 0; // reset the mask for (int i = 0; i < 8; i++) { - final Tile t2 = context.getAdjacentTile(Sides.get(i)); + final Tile t2 = context.getAdjacentTile(Moves.getSide(i)); if (!t2.isNull() && t2.doesCastShadow()) { - shadows |= Sides.bit(i); + shadows |= Moves.getBit(i); } } @@ -90,16 +91,22 @@ public abstract class TileRenderer implements Updateable { if (shadows == 0) return; final Rect rect = context.getRect(); - if ((shadows & Sides.NW_CORNER) == Sides.MASK_NW) Render.quadTextured(rect, SH_NW); - if ((shadows & Sides.MASK_N) != 0) Render.quadTextured(rect, SH_N); - if ((shadows & Sides.NE_CORNER) == Sides.MASK_NE) Render.quadTextured(rect, SH_NE); + if ((shadows & Moves.BITS_NW_CORNER) == Moves.BIT_NW) Render.quadTextured(rect, SH_NW); + if ((shadows & Moves.BIT_N) != 0) Render.quadTextured(rect, SH_N); + if ((shadows & Moves.BITS_NE_CORNER) == Moves.BIT_NE) Render.quadTextured(rect, SH_NE); - if ((shadows & Sides.MASK_W) != 0) Render.quadTextured(rect, SH_W); - if ((shadows & Sides.MASK_E) != 0) Render.quadTextured(rect, SH_E); + if ((shadows & Moves.BIT_W) != 0) Render.quadTextured(rect, SH_W); + if ((shadows & Moves.BIT_E) != 0) Render.quadTextured(rect, SH_E); - if ((shadows & Sides.SW_CORNER) == Sides.MASK_SW) Render.quadTextured(rect, SH_SW); - if ((shadows & Sides.MASK_S) != 0) Render.quadTextured(rect, SH_S); - if ((shadows & Sides.SE_CORNER) == Sides.MASK_SE) Render.quadTextured(rect, SH_SE); + if ((shadows & Moves.BITS_SW_CORNER) == Moves.BIT_SW) Render.quadTextured(rect, SH_SW); + if ((shadows & Moves.BIT_S) != 0) Render.quadTextured(rect, SH_S); + if ((shadows & Moves.BITS_SE_CORNER) == Moves.BIT_SE) Render.quadTextured(rect, SH_SE); + } + + + @DefaultImpl + public void renderExtra(TileRenderContext context) + { } @@ -117,24 +124,24 @@ public abstract class TileRenderer implements Updateable { byte ufog = 0; for (int i = 0; i < 8; i++) { - final Tile t2 = context.getAdjacentTile(Sides.get(i)); + final Tile t2 = context.getAdjacentTile(Moves.getSide(i)); if (t2.isNull() || !t2.isExplored()) { - ufog |= Sides.bit(i); + ufog |= Moves.getBit(i); } } if (ufog == 0) return; - if ((ufog & Sides.NW_CORNER) == Sides.MASK_NW) Render.quadTextured(rect, UFOG_NW); - if ((ufog & Sides.MASK_N) != 0) Render.quadTextured(rect, UFOG_N); - if ((ufog & Sides.NE_CORNER) == Sides.MASK_NE) Render.quadTextured(rect, UFOG_NE); + if ((ufog & Moves.BITS_NW_CORNER) == Moves.BIT_NW) Render.quadTextured(rect, UFOG_NW); + if ((ufog & Moves.BIT_N) != 0) Render.quadTextured(rect, UFOG_N); + if ((ufog & Moves.BITS_NE_CORNER) == Moves.BIT_NE) Render.quadTextured(rect, UFOG_NE); - if ((ufog & Sides.MASK_W) != 0) Render.quadTextured(rect, UFOG_W); - if ((ufog & Sides.MASK_E) != 0) Render.quadTextured(rect, UFOG_E); + if ((ufog & Moves.BIT_W) != 0) Render.quadTextured(rect, UFOG_W); + if ((ufog & Moves.BIT_E) != 0) Render.quadTextured(rect, UFOG_E); - if ((ufog & Sides.SW_CORNER) == Sides.MASK_SW) Render.quadTextured(rect, UFOG_SW); - if ((ufog & Sides.MASK_S) != 0) Render.quadTextured(rect, UFOG_S); - if ((ufog & Sides.SE_CORNER) == Sides.MASK_SE) Render.quadTextured(rect, UFOG_SE); + if ((ufog & Moves.BITS_SW_CORNER) == Moves.BIT_SW) Render.quadTextured(rect, UFOG_SW); + if ((ufog & Moves.BIT_S) != 0) Render.quadTextured(rect, UFOG_S); + if ((ufog & Moves.BITS_SE_CORNER) == Moves.BIT_SE) Render.quadTextured(rect, UFOG_SE); } diff --git a/src/mightypork/rogue/world/tile/TileType.java b/src/mightypork/rogue/world/tile/TileType.java index 4c1a8d6..4528b51 100644 --- a/src/mightypork/rogue/world/tile/TileType.java +++ b/src/mightypork/rogue/world/tile/TileType.java @@ -2,8 +2,6 @@ package mightypork.rogue.world.tile; import mightypork.gamecore.util.math.color.Color; -import mightypork.gamecore.util.math.color.pal.PAL16; -import mightypork.gamecore.util.math.color.pal.RGB; /** @@ -14,25 +12,25 @@ import mightypork.gamecore.util.math.color.pal.RGB; public enum TileType { /** No tile */ - NULL(RGB.NONE, false), + NULL(TileColors.NULL, false), /** Floor tile */ - FLOOR(RGB.GRAY_DARK, true), + FLOOR(TileColors.FLOOR, true), /** Wall tile */ - WALL(RGB.GRAY_LIGHT, false), + WALL(TileColors.WALL, false), /** Door/gate tile */ - DOOR(PAL16.NEWPOOP, true), + DOOR(TileColors.DOOR, true), /** Passage (ie secret door) */ - PASSAGE(RGB.GRAY, true), + PASSAGE(TileColors.COLLAPSED_WALL, true), /** Stairs */ - STAIRS(RGB.CYAN, false); + STAIRS(TileColors.WALL, false); private final Color mapColor; private final boolean potentiallyWalkable; - private TileType(Color mapColor, boolean potentiallyWalkable) + private TileType(Color defaultMapColor, boolean potentiallyWalkable) { - this.mapColor = mapColor; + this.mapColor = defaultMapColor; this.potentiallyWalkable = potentiallyWalkable; } diff --git a/src/mightypork/rogue/world/tile/Tiles.java b/src/mightypork/rogue/world/tile/Tiles.java index 2e92ea8..bf3fcf5 100644 --- a/src/mightypork/rogue/world/tile/Tiles.java +++ b/src/mightypork/rogue/world/tile/Tiles.java @@ -27,6 +27,7 @@ public final class Tiles { public static final TileModel BRICK_HIDDEN_DOOR = new TileModel(14, TileBrickSecretDoor.class); public static final TileModel BRICK_ENTRANCE = new TileModel(15, TileBrickEntrance.class); public static final TileModel BRICK_EXIT = new TileModel(16, TileBrickExit.class); + public static final TileModel BRICK_CHEST = new TileModel(17, TileBrickChest.class); public static void register(int id, TileModel model) diff --git a/src/mightypork/rogue/world/tile/impl/TileBaseChest.java b/src/mightypork/rogue/world/tile/impl/TileBaseChest.java new file mode 100644 index 0000000..fb12d29 --- /dev/null +++ b/src/mightypork/rogue/world/tile/impl/TileBaseChest.java @@ -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; + } +} diff --git a/src/mightypork/rogue/world/tile/impl/TileBaseEntrance.java b/src/mightypork/rogue/world/tile/impl/TileBaseEntrance.java index c232d5d..ed089dd 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseEntrance.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseEntrance.java @@ -2,7 +2,9 @@ package mightypork.rogue.world.tile.impl; import mightypork.gamecore.util.math.algo.Coord; +import mightypork.gamecore.util.math.color.Color; import mightypork.rogue.world.events.WorldAscendRequest; +import mightypork.rogue.world.tile.TileColors; import mightypork.rogue.world.tile.TileModel; @@ -31,4 +33,11 @@ public abstract class TileBaseEntrance extends TileBaseStairs { { return false; } + + + @Override + public Color getMapColor() + { + return TileColors.ENTRANCE; + } } diff --git a/src/mightypork/rogue/world/tile/impl/TileBaseExit.java b/src/mightypork/rogue/world/tile/impl/TileBaseExit.java index 32432ae..47e8388 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseExit.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseExit.java @@ -2,7 +2,9 @@ package mightypork.rogue.world.tile.impl; import mightypork.gamecore.util.math.algo.Coord; +import mightypork.gamecore.util.math.color.Color; import mightypork.rogue.world.events.WorldDescendRequest; +import mightypork.rogue.world.tile.TileColors; import mightypork.rogue.world.tile.TileModel; @@ -31,4 +33,11 @@ public abstract class TileBaseExit extends TileBaseStairs { { return false; } + + + @Override + public Color getMapColor() + { + return TileColors.EXIT; + } } diff --git a/src/mightypork/rogue/world/tile/impl/TileBaseSecretDoor.java b/src/mightypork/rogue/world/tile/impl/TileBaseSecretDoor.java index 6935fa6..c626b44 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseSecretDoor.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseSecretDoor.java @@ -6,16 +6,14 @@ import java.io.IOException; import mightypork.gamecore.resources.textures.TxSheet; import mightypork.gamecore.util.ion.IonInput; import mightypork.gamecore.util.ion.IonOutput; -import mightypork.gamecore.util.math.Calc; import mightypork.gamecore.util.math.color.Color; -import mightypork.gamecore.util.math.color.pal.RGB; +import mightypork.rogue.world.tile.TileColors; import mightypork.rogue.world.tile.TileModel; -import mightypork.rogue.world.tile.TileType; public abstract class TileBaseSecretDoor extends TileBaseDoor { - private int clicks = Calc.randInt(2, 3); + private int clicks = 2; public TileBaseSecretDoor(TileModel model, TxSheet secret, TxSheet closed, TxSheet open) @@ -43,8 +41,8 @@ public abstract class TileBaseSecretDoor extends TileBaseDoor { @Override public Color getMapColor() { - if (locked) return TileType.WALL.getMapColor(); - return RGB.PINK; + if (locked) return TileColors.SECRET_DOOR_HIDDEN; + return TileColors.SECRET_DOOR_REVEALED; } diff --git a/src/mightypork/rogue/world/tile/impl/TileWithItems.java b/src/mightypork/rogue/world/tile/impl/TileWithItems.java index f756ac1..f8352f1 100644 --- a/src/mightypork/rogue/world/tile/impl/TileWithItems.java +++ b/src/mightypork/rogue/world/tile/impl/TileWithItems.java @@ -31,12 +31,20 @@ public abstract class TileWithItems extends Tile { @Override public void renderExtra(TileRenderContext context) { - if ((isExplored() || !Config.RENDER_UFOG) && !items.isEmpty()) { + super.renderExtra(context); + + if ((isExplored() || !Config.RENDER_UFOG) && hasItem() && shouldRenderItems()) { itemRenderer.render(items, context); } } + protected boolean shouldRenderItems() + { + return true; + } + + @Override public void updateTile(double delta) { diff --git a/src/mightypork/rogue/world/tile/impl/brick/TileBrickChest.java b/src/mightypork/rogue/world/tile/impl/brick/TileBrickChest.java new file mode 100644 index 0000000..1fd1560 --- /dev/null +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickChest.java @@ -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")); + } + +} diff --git a/src/mightypork/rogue/world/tile/impl/brick/TileBrickDoor.java b/src/mightypork/rogue/world/tile/impl/brick/TileBrickDoor.java index 49a9920..535a0f2 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickDoor.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickDoor.java @@ -13,9 +13,9 @@ public class TileBrickDoor extends TileBaseDoor { //@formatter:off super( model, - Res.txs("tile.brick.door.closed"), // LOCKED - Res.txs("tile.brick.door.closed"), - Res.txs("tile.brick.door.open") + Res.getTxSheet("tile.brick.door.closed"), // LOCKED + Res.getTxSheet("tile.brick.door.closed"), + Res.getTxSheet("tile.brick.door.open") ); //@formatter:on } diff --git a/src/mightypork/rogue/world/tile/impl/brick/TileBrickEntrance.java b/src/mightypork/rogue/world/tile/impl/brick/TileBrickEntrance.java index fbe673d..8181ad4 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickEntrance.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickEntrance.java @@ -19,7 +19,7 @@ public class TileBrickEntrance extends TileBaseEntrance { @Override protected TileRenderer makeRenderer() { - return new OneFrameTileRenderer(this, Res.txq("tile.brick.stairs.up")); + return new OneFrameTileRenderer(this, Res.getTxQuad("tile.brick.stairs.up")); } } diff --git a/src/mightypork/rogue/world/tile/impl/brick/TileBrickExit.java b/src/mightypork/rogue/world/tile/impl/brick/TileBrickExit.java index a4c4bdd..b55843e 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickExit.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickExit.java @@ -19,7 +19,7 @@ public class TileBrickExit extends TileBaseExit { @Override protected TileRenderer makeRenderer() { - return new OneFrameTileRenderer(this, Res.txq("tile.brick.stairs.down")); + return new OneFrameTileRenderer(this, Res.getTxQuad("tile.brick.stairs.down")); } } diff --git a/src/mightypork/rogue/world/tile/impl/brick/TileBrickFloor.java b/src/mightypork/rogue/world/tile/impl/brick/TileBrickFloor.java index a4768fd..d223c9c 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickFloor.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickFloor.java @@ -10,7 +10,7 @@ public class TileBrickFloor extends TileBaseFloor { public TileBrickFloor(TileModel model) { - super(model, Res.txs("tile.brick.floor")); + super(model, Res.getTxSheet("tile.brick.floor")); } } diff --git a/src/mightypork/rogue/world/tile/impl/brick/TileBrickPassage.java b/src/mightypork/rogue/world/tile/impl/brick/TileBrickPassage.java index 53e6b55..c2beb61 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickPassage.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickPassage.java @@ -10,7 +10,7 @@ public class TileBrickPassage extends TileBasePassage { public TileBrickPassage(TileModel model) { - super(model, Res.txs("tile.brick.passage")); + super(model, Res.getTxSheet("tile.brick.passage")); } } diff --git a/src/mightypork/rogue/world/tile/impl/brick/TileBrickSecretDoor.java b/src/mightypork/rogue/world/tile/impl/brick/TileBrickSecretDoor.java index ee0ed66..24cf67d 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickSecretDoor.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickSecretDoor.java @@ -13,9 +13,9 @@ public class TileBrickSecretDoor extends TileBaseSecretDoor { //@formatter:off super( model, - Res.txs("tile.brick.door.secret"), - Res.txs("tile.brick.door.closed"), - Res.txs("tile.brick.door.open") + Res.getTxSheet("tile.brick.door.secret"), + Res.getTxSheet("tile.brick.door.closed"), + Res.getTxSheet("tile.brick.door.open") ); //@formatter:on diff --git a/src/mightypork/rogue/world/tile/impl/brick/TileBrickWall.java b/src/mightypork/rogue/world/tile/impl/brick/TileBrickWall.java index 16ee744..fea5704 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickWall.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickWall.java @@ -10,7 +10,7 @@ public class TileBrickWall extends TileBaseWall { public TileBrickWall(TileModel model) { - super(model, Res.txs("tile.brick.wall")); + super(model, Res.getTxSheet("tile.brick.wall")); } } diff --git a/src/mightypork/rogue/world/tile/render/ChestRenderer.java b/src/mightypork/rogue/world/tile/render/ChestRenderer.java new file mode 100644 index 0000000..0db3ad8 --- /dev/null +++ b/src/mightypork/rogue/world/tile/render/ChestRenderer.java @@ -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); + } + } + } +}