diff --git a/res/img/tiles16.png b/res/img/tiles16.png index 0ba6218..b4adbe2 100644 Binary files a/res/img/tiles16.png and b/res/img/tiles16.png differ diff --git a/res/img/tiles16.xcf b/res/img/tiles16.xcf index f7ee4b6..cac826d 100644 Binary files a/res/img/tiles16.xcf and b/res/img/tiles16.xcf differ diff --git a/src/mightypork/gamecore/render/Render.java b/src/mightypork/gamecore/render/Render.java index 2b0e94e..e3afe42 100644 --- a/src/mightypork/gamecore/render/Render.java +++ b/src/mightypork/gamecore/render/Render.java @@ -455,7 +455,9 @@ public class Render { final RectDigest q = quad.digest(); final RectDigest u = txquad.uvs.digest(); - double tL = u.left, tR = u.right, tT = u.top, tB = u.bottom; + final double offs = 0.0001;// hack to avoid white stitching + + double tL = u.left + offs, tR = u.right - offs, tT = u.top + offs, tB = u.bottom - offs; // handle flip if (txquad.isFlippedY()) { diff --git a/src/mightypork/rogue/App.java b/src/mightypork/rogue/App.java index d7c44bf..e0b776e 100644 --- a/src/mightypork/rogue/App.java +++ b/src/mightypork/rogue/App.java @@ -160,7 +160,7 @@ public final class App extends BaseApp { protected void postInit() { // TODO tmp - WorldProvider.get().createWorld(42); + WorldProvider.get().createWorld(Double.doubleToLongBits(Math.random())); getEventBus().send(new CrossfadeRequest("menu", true)); } diff --git a/src/mightypork/rogue/Const.java b/src/mightypork/rogue/Const.java index 1fc5ec9..f6806f9 100644 --- a/src/mightypork/rogue/Const.java +++ b/src/mightypork/rogue/Const.java @@ -15,7 +15,7 @@ public final class Const { public static final String TITLEBAR = APP_NAME + " v." + VERSION; // AUDIO - public static final int FPS_RENDER = 100; // max + public static final int FPS_RENDER = 120; // max // INITIAL WINDOW SIZE public static final int WINDOW_W = 800; diff --git a/src/mightypork/rogue/Res.java b/src/mightypork/rogue/Res.java index 81426d6..1318865 100644 --- a/src/mightypork/rogue/Res.java +++ b/src/mightypork/rogue/Res.java @@ -85,12 +85,13 @@ public final class Res { tiles = texture.grid(8, 8); textures.addSheet("tile.brick.floor", tiles.makeSheet(0, 1, 5, 1)); - textures.addSheet("tile.brick.wall", tiles.makeSheet(0, 0, 5, 1)); + textures.addSheet("tile.brick.wall", tiles.makeSheet(0, 0, 8, 1)); textures.addSheet("tile.brick.door.closed", tiles.makeSheet(1, 2, 1, 1)); textures.addSheet("tile.brick.door.open", tiles.makeSheet(2, 2, 1, 1)); + textures.addSheet("tile.brick.door.secret", tiles.makeSheet(0, 3, 2, 1)); - textures.addSheet("tile.brick.passage", tiles.makeSheet(3, 2, 2, 1)); + textures.addSheet("tile.brick.passage", tiles.makeSheet(3, 2, 4, 1)); textures.addQuad("tile.shadow.n", tiles.makeQuad(0, 7)); textures.addQuad("tile.shadow.s", tiles.makeQuad(0, 7).flipY()); diff --git a/src/mightypork/rogue/screens/game/WorldLayer.java b/src/mightypork/rogue/screens/game/WorldLayer.java index 3ca2ba7..5bfd500 100644 --- a/src/mightypork/rogue/screens/game/WorldLayer.java +++ b/src/mightypork/rogue/screens/game/WorldLayer.java @@ -7,6 +7,8 @@ import mightypork.gamecore.util.math.constraints.num.Num; import mightypork.rogue.world.gui.MapView; import mightypork.rogue.world.gui.interaction.MIPClickPathfWalk; import mightypork.rogue.world.gui.interaction.MIPKeyWalk; +import mightypork.rogue.world.gui.interaction.MIPMouseWalk; +import mightypork.rogue.world.gui.interaction.MIPTileClick; public class WorldLayer extends ScreenLayer { @@ -24,8 +26,9 @@ public class WorldLayer extends ScreenLayer { // map input plugins worldView.addPlugin(new MIPKeyWalk()); + worldView.addPlugin(new MIPTileClick()); worldView.addPlugin(new MIPClickPathfWalk()); - //worldView.addPlugin(new MIPMouseWalk()); + worldView.addPlugin(new MIPMouseWalk()); // size of lower navbar final Num lownav = root.width().min(root.height()).max(700).perc(7); diff --git a/src/mightypork/rogue/world/PlayerControl.java b/src/mightypork/rogue/world/PlayerControl.java index 7c53be1..e9add8c 100644 --- a/src/mightypork/rogue/world/PlayerControl.java +++ b/src/mightypork/rogue/world/PlayerControl.java @@ -48,34 +48,31 @@ public abstract class PlayerControl { public void goNorth() { - getPlayerEntity().pos.cancelPath(); - getPlayerEntity().pos.addStep(Step.NORTH); + go(Step.NORTH); } public void goSouth() { - getPlayerEntity().pos.cancelPath(); - getPlayerEntity().pos.addStep(Step.SOUTH); + go(Step.SOUTH); } public void goEast() { - getPlayerEntity().pos.cancelPath(); - getPlayerEntity().pos.addStep(Step.EAST); + go(Step.EAST); } public void goWest() { - getPlayerEntity().pos.cancelPath(); - getPlayerEntity().pos.addStep(Step.WEST); + go(Step.WEST); } public void navigateTo(Coord pos) { + if (!getLevel().getTile(pos).isExplored()) return; getPlayerEntity().pos.navigateTo(pos); } @@ -99,4 +96,31 @@ public abstract class PlayerControl { { return getPlayerEntity().pos.getCoord(); } + + + public boolean canGo(Step side) + { + return getLevel().getTile(getCoord().add(side)).isWalkable(); + } + + + public boolean clickTile(Step side) + { + return clickTile(getCoord().add(side)); + } + + + public boolean clickTile(Coord pos) + { + if (pos.dist(getCoord()) > 8) return false; // too far + + return getLevel().getTile(pos).onClick(); + } + + + public void go(Step side) + { + getPlayerEntity().pos.cancelPath(); + getPlayerEntity().pos.addStep(side); + } } diff --git a/src/mightypork/rogue/world/entity/EntityModule.java b/src/mightypork/rogue/world/entity/EntityModule.java index 8abc83a..db8c3ed 100644 --- a/src/mightypork/rogue/world/entity/EntityModule.java +++ b/src/mightypork/rogue/world/entity/EntityModule.java @@ -18,7 +18,7 @@ import mightypork.gamecore.util.ion.IonObjBundled; public abstract class EntityModule implements IonObjBundled, Updateable { protected final Entity entity; - protected final Random rand = new Random(); + protected static final Random rand = new Random(); public EntityModule(Entity entity) diff --git a/src/mightypork/rogue/world/entity/entities/PlayerEntity.java b/src/mightypork/rogue/world/entity/entities/PlayerEntity.java index 9be40e8..de8c817 100644 --- a/src/mightypork/rogue/world/entity/entities/PlayerEntity.java +++ b/src/mightypork/rogue/world/entity/entities/PlayerEntity.java @@ -110,5 +110,4 @@ public class PlayerEntity extends Entity { { return EntityType.PLAYER; } - } diff --git a/src/mightypork/rogue/world/gen/LevelGenerator.java b/src/mightypork/rogue/world/gen/LevelGenerator.java index 9e79b35..3bb7724 100644 --- a/src/mightypork/rogue/world/gen/LevelGenerator.java +++ b/src/mightypork/rogue/world/gen/LevelGenerator.java @@ -4,8 +4,7 @@ package mightypork.rogue.world.gen; import java.util.Random; import mightypork.gamecore.util.math.algo.Coord; -import mightypork.rogue.world.gen.rooms.DeadEndRoom; -import mightypork.rogue.world.gen.rooms.SimpleRectRoom; +import mightypork.rogue.world.gen.rooms.Rooms; import mightypork.rogue.world.gen.themes.ThemeBrick; import mightypork.rogue.world.level.Level; @@ -14,9 +13,6 @@ public class LevelGenerator { public static final MapTheme DUNGEON_THEME = new ThemeBrick(); - public static final RoomBuilder ROOM_SQUARE = new SimpleRectRoom(); - private static final RoomBuilder DEAD_END = new DeadEndRoom(); - public static Level build(long seed, int complexity, MapTheme theme) { @@ -27,11 +23,12 @@ public class LevelGenerator { final ScratchMap map = new ScratchMap(max_size, theme, rand); // start - map.addRoom(ROOM_SQUARE); + map.addRoom(Rooms.BASIC); for (int i = 0; i < 2 + complexity / 2 + rand.nextInt((int) (1 + complexity * 0.3)); i++) { - map.addRoom(ROOM_SQUARE); - if (rand.nextInt(6) > 0) map.addRoom(DEAD_END); + map.addRoom(Rooms.BASIC); + if (rand.nextInt(7) > 0) map.addRoom(Rooms.SECRET); + if (rand.nextInt(6) > 0) map.addRoom(Rooms.DEAD_END); } map.buildCorridors(); diff --git a/src/mightypork/rogue/world/gen/MapTheme.java b/src/mightypork/rogue/world/gen/MapTheme.java index dda3a80..e3704e1 100644 --- a/src/mightypork/rogue/world/gen/MapTheme.java +++ b/src/mightypork/rogue/world/gen/MapTheme.java @@ -21,4 +21,7 @@ public interface MapTheme { TileModel passage(); + + + TileModel secretDoor(); } diff --git a/src/mightypork/rogue/world/gen/ScratchMap.java b/src/mightypork/rogue/world/gen/ScratchMap.java index 2f94705..31a37fe 100644 --- a/src/mightypork/rogue/world/gen/ScratchMap.java +++ b/src/mightypork/rogue/world/gen/ScratchMap.java @@ -42,7 +42,9 @@ public class ScratchMap { @Override public boolean isAccessible(Coord pos) { - return isIn(pos); // suffices for now + if (!isIn(pos)) return false; + final Tile t = get(pos); + return t.isPotentiallyWalkable() || (t.genData.protection != TileProtectLevel.STRONG); } @@ -63,7 +65,7 @@ public class ScratchMap { return 20; case WALL: - if (t.genData.isProtected) return 2000; + if (t.genData.protection != TileProtectLevel.NONE) return 2000; return 100; @@ -220,14 +222,14 @@ public class ScratchMap { } - public void protect(Coord min, Coord max) + public void protect(Coord min, Coord max, TileProtectLevel prot) { if (!isIn(min) || !isIn(max)) throw new IndexOutOfBoundsException("Tile(s) not in map: " + min + " , " + max); final Coord c = Coord.make(0, 0); for (c.x = min.x; c.x <= max.x; c.x++) for (c.y = min.y; c.y <= max.y; c.y++) - get(c).genData.isProtected = true; + get(c).genData.protection = prot; } diff --git a/src/mightypork/rogue/world/gen/TileProtectLevel.java b/src/mightypork/rogue/world/gen/TileProtectLevel.java new file mode 100644 index 0000000..65d58f8 --- /dev/null +++ b/src/mightypork/rogue/world/gen/TileProtectLevel.java @@ -0,0 +1,7 @@ +package mightypork.rogue.world.gen; + + +public enum TileProtectLevel +{ + NONE, WEAK, STRONG; +} diff --git a/src/mightypork/rogue/world/gen/rooms/AbstractRectRoom.java b/src/mightypork/rogue/world/gen/rooms/AbstractRectRoom.java new file mode 100644 index 0000000..3a20fcd --- /dev/null +++ b/src/mightypork/rogue/world/gen/rooms/AbstractRectRoom.java @@ -0,0 +1,99 @@ +package mightypork.rogue.world.gen.rooms; + + +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.rogue.world.gen.MapTheme; +import mightypork.rogue.world.gen.RoomBuilder; +import mightypork.rogue.world.gen.RoomDesc; +import mightypork.rogue.world.gen.ScratchMap; +import mightypork.rogue.world.gen.TileProtectLevel; +import mightypork.rogue.world.tile.TileModel; + + +public abstract class AbstractRectRoom implements RoomBuilder { + + @Override + public RoomDesc buildToFit(ScratchMap map, MapTheme theme, Random rand, Coord center) + { + // half width, half height actually + final Coord innerSize = getInnerSize(rand); + final int width = 2 + innerSize.x; + final int height = 2 + innerSize.y; + + final int wLow = width / 2; + final int wHigh = width - wLow; + final int hLow = height / 2; + final int hHigh = height - hLow; + + final Coord min = new Coord(center.x - wLow, center.y - hLow); + final Coord max = new Coord(center.x + wHigh, center.y + hHigh); + + if (!map.isClear(min.add(-1, -1), max)) return null; + + map.fill(min, max, theme.floor()); + map.border(min, max, theme.wall()); + map.protect(min, max, getWallProtectionLevel()); + + placeDoors(map, theme, rand, min, max); + + buildExtras(map, theme, rand, min, max); + + return new RoomDesc(min.add(-1, -1), max); + } + + + protected void placeDoors(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max) + { + final int width = max.x - min.x; + final int height = max.y - min.y; + + for (int i = 0, j = 0; i <= getDoorCount(rand) && j < 100; j++) { // j is to prevent inf loop + final Coord door = min.copy(); + switch (rand.nextInt(4)) { + case 0: + door.y = min.y; + door.x += 1 + rand.nextInt(width - 1); + break; + case 1: + door.y = max.y; + door.x += 1 + rand.nextInt(width - 1); + break; + case 2: + door.x = min.x; + door.y += 1 + rand.nextInt(height - 1); + break; + case 3: + door.x = max.x; + door.y += 1 + rand.nextInt(height - 1); + break; + } + + if ((map.findDoors(door) & Sides.CARDINAL) == 0) { + map.set(door, getDoorType(theme, rand)); + i++; // increment pointer + } + } + } + + + @DefaultImpl + protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max) + { + } + + + protected abstract Coord getInnerSize(Random rand); + + + protected abstract TileProtectLevel getWallProtectionLevel(); + + + protected abstract TileModel getDoorType(MapTheme theme, Random rand); + + + protected abstract int getDoorCount(Random rand); +} diff --git a/src/mightypork/rogue/world/gen/rooms/BasicRoom.java b/src/mightypork/rogue/world/gen/rooms/BasicRoom.java new file mode 100644 index 0000000..2a4a9e0 --- /dev/null +++ b/src/mightypork/rogue/world/gen/rooms/BasicRoom.java @@ -0,0 +1,41 @@ +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.TileProtectLevel; +import mightypork.rogue.world.tile.TileModel; + + +public class BasicRoom extends AbstractRectRoom { + + + @Override + protected TileModel getDoorType(MapTheme theme, Random rand) + { + return rand.nextInt(4) == 0 ? theme.passage() : theme.door(); + } + + + @Override + protected int getDoorCount(Random rand) + { + return 1 + rand.nextInt(5); + } + + + @Override + protected TileProtectLevel getWallProtectionLevel() + { + return TileProtectLevel.WEAK; + } + + + @Override + protected Coord getInnerSize(Random rand) + { + return Coord.make(3 + rand.nextInt(3), 3 + rand.nextInt(3)); + } +} diff --git a/src/mightypork/rogue/world/gen/rooms/Rooms.java b/src/mightypork/rogue/world/gen/rooms/Rooms.java new file mode 100644 index 0000000..1a3add8 --- /dev/null +++ b/src/mightypork/rogue/world/gen/rooms/Rooms.java @@ -0,0 +1,12 @@ +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 SECRET = new SecretRoom(); + public static final RoomBuilder DEAD_END = new DeadEndRoom(); +} diff --git a/src/mightypork/rogue/world/gen/rooms/SecretRoom.java b/src/mightypork/rogue/world/gen/rooms/SecretRoom.java new file mode 100644 index 0000000..d024ccc --- /dev/null +++ b/src/mightypork/rogue/world/gen/rooms/SecretRoom.java @@ -0,0 +1,41 @@ +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.TileProtectLevel; +import mightypork.rogue.world.tile.TileModel; + + +public class SecretRoom extends AbstractRectRoom { + + + @Override + protected TileModel getDoorType(MapTheme theme, Random rand) + { + return theme.secretDoor(); + } + + + @Override + protected int getDoorCount(Random rand) + { + return 1 + rand.nextInt(2); + } + + + @Override + protected TileProtectLevel getWallProtectionLevel() + { + return TileProtectLevel.STRONG; + } + + + @Override + protected Coord getInnerSize(Random rand) + { + return Coord.make(3 + rand.nextInt(2), 3 + rand.nextInt(2)); + } +} diff --git a/src/mightypork/rogue/world/gen/rooms/SimpleRectRoom.java b/src/mightypork/rogue/world/gen/rooms/SimpleRectRoom.java deleted file mode 100644 index 1ccc9a3..0000000 --- a/src/mightypork/rogue/world/gen/rooms/SimpleRectRoom.java +++ /dev/null @@ -1,72 +0,0 @@ -package mightypork.rogue.world.gen.rooms; - - -import java.util.Random; - -import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Sides; -import mightypork.rogue.world.gen.MapTheme; -import mightypork.rogue.world.gen.RoomBuilder; -import mightypork.rogue.world.gen.RoomDesc; -import mightypork.rogue.world.gen.ScratchMap; -import mightypork.rogue.world.tile.TileModel; - - -public class SimpleRectRoom implements RoomBuilder { - - @Override - public RoomDesc buildToFit(ScratchMap map, MapTheme theme, Random rand, Coord center) - { - // half width, half height actually - final int width = 2 + rand.nextInt(2); - final int height = 2 + rand.nextInt(2); - - final Coord min = new Coord(center.x - width, center.y - height); - final Coord max = new Coord(center.x + width, center.y + height); - - if (!map.isClear(min, max)) return null; - - map.fill(min, max, theme.floor()); - map.border(min, max, theme.wall()); - map.protect(min, max); - - final boolean holes = rand.nextInt(4) == 0; - - for (int i = 0; i <= 2 + rand.nextInt(6); i++) { - final Coord door = min.copy(); - switch (rand.nextInt(4)) { - case 0: - door.y = min.y; - door.x += 1 + rand.nextInt((width - 1) * 2); - break; - case 1: - door.y = max.y; - door.x += 1 + rand.nextInt((width - 1) * 2); - break; - case 2: - door.x = min.x; - door.y += 1 + rand.nextInt((height - 1) * 2); - break; - case 3: - door.x = max.x; - door.y += 1 + rand.nextInt((height - 1) * 2); - break; - } - - if ((map.findDoors(door) & Sides.CARDINAL) == 0) { - TileModel placed; - switch (rand.nextInt(8)) { - case 0: - case 1: - placed = theme.passage(); - break; - default: - placed = holes ? theme.floor() : theme.door(); - } - map.set(door, placed); - } - } - - return new RoomDesc(min.add(-1, -1), max); - } -} diff --git a/src/mightypork/rogue/world/gen/themes/ThemeBrick.java b/src/mightypork/rogue/world/gen/themes/ThemeBrick.java index fa11bb8..1695c10 100644 --- a/src/mightypork/rogue/world/gen/themes/ThemeBrick.java +++ b/src/mightypork/rogue/world/gen/themes/ThemeBrick.java @@ -35,4 +35,11 @@ public class ThemeBrick implements MapTheme { { return Tiles.BRICK_PASSAGE; } + + + @Override + public TileModel secretDoor() + { + return Tiles.BRICK_HIDDEN_DOOR; + } } diff --git a/src/mightypork/rogue/world/gui/MapView.java b/src/mightypork/rogue/world/gui/MapView.java index bd8325b..f4516ad 100644 --- a/src/mightypork/rogue/world/gui/MapView.java +++ b/src/mightypork/rogue/world/gui/MapView.java @@ -1,7 +1,7 @@ package mightypork.rogue.world.gui; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Set; import mightypork.gamecore.eventbus.events.Updateable; @@ -33,7 +33,7 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL protected final WorldRenderer worldRenderer; private final PlayerControl pc; - private final Set plugins = new HashSet<>(); + private final Set plugins = new LinkedHashSet<>(); private final NumAnimated zoom = new NumAnimated(0, Easing.SINE_BOTH); private final Num tileSize; @@ -71,7 +71,7 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL public void onStepFinished() { for (final MapInteractionPlugin p : plugins) { - p.onStepEnd(this, pc); + if (p.onStepEnd(this, pc)) break; } } @@ -80,7 +80,7 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL public void onPathFinished() { for (final MapInteractionPlugin p : plugins) { - p.onStepEnd(this, pc); + if (p.onStepEnd(this, pc)) break; } } @@ -89,7 +89,7 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL public void onPathInterrupted() { for (final MapInteractionPlugin p : plugins) { - p.onStepEnd(this, pc); + if (p.onStepEnd(this, pc)) break; } } @@ -100,10 +100,11 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL if (!event.isOver(this)) return; for (final MapInteractionPlugin p : plugins) { - p.onClick(this, pc, event.getPos(), event.getButton(), event.isDown()); + if (p.onClick(this, pc, event.getPos(), event.getButton(), event.isDown())) { + event.consume(); + break; + } } - - event.consume(); // only our clicks. } @@ -111,7 +112,7 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL public void receive(KeyEvent event) { for (final MapInteractionPlugin p : plugins) { - p.onKey(this, pc, event.getKey(), event.isDown()); + if (p.onKey(this, pc, event.getKey(), event.isDown())) break; } if (event.getKey() == Keys.Z) { @@ -120,8 +121,6 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL } else { zoom.fadeOut(1); } - - } // don't consume key events, can be useful for others. @@ -142,6 +141,9 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL @Override public void update(double delta) { + for (final MapInteractionPlugin p : plugins) { + p.update(this, pc, delta); + } zoom.update(delta); } } diff --git a/src/mightypork/rogue/world/gui/interaction/MIPClickPathfWalk.java b/src/mightypork/rogue/world/gui/interaction/MIPClickPathfWalk.java index f142020..fb3157c 100644 --- a/src/mightypork/rogue/world/gui/interaction/MIPClickPathfWalk.java +++ b/src/mightypork/rogue/world/gui/interaction/MIPClickPathfWalk.java @@ -1,11 +1,11 @@ package mightypork.rogue.world.gui.interaction; -import mightypork.gamecore.input.InputSystem; import mightypork.gamecore.util.math.algo.Coord; import mightypork.gamecore.util.math.constraints.vect.Vect; import mightypork.rogue.world.PlayerControl; import mightypork.rogue.world.gui.MapView; +import mightypork.rogue.world.tile.Tile; public class MIPClickPathfWalk implements MapInteractionPlugin { @@ -14,29 +14,47 @@ public class MIPClickPathfWalk implements MapInteractionPlugin { @Override - public void onStepEnd(MapView view, PlayerControl player) + public void update(MapView view, PlayerControl player, double delta) { - if (InputSystem.isMouseButtonDown(BTN)) { - final Coord clicked = view.toWorldPos(InputSystem.getMousePos()); - player.navigateTo(clicked); - } +// if (InputSystem.isMouseButtonDown(BTN)) { +// +// troToNav(view, player, InputSystem.getMousePos()); +// } } @Override - public void onClick(MapView view, PlayerControl player, Vect mouse, int button, boolean down) + public boolean onClick(MapView view, PlayerControl player, Vect mouse, int button, boolean down) { - if (!down || button != BTN) return; + if (down || button != BTN) return false; + return troToNav(view, player, mouse); + } + + + private boolean troToNav(MapView view, PlayerControl player, Vect mouse) + { final Coord clicked = view.toWorldPos(mouse); + final Tile t = player.getLevel().getTile(clicked); + if (!t.isWalkable() || !t.isExplored()) return false; + player.navigateTo(clicked); + return true; + } + + + @Override + public boolean onKey(MapView view, PlayerControl player, int key, boolean down) + { + return false; } @Override - public void onKey(MapView view, PlayerControl player, int key, boolean down) + public boolean onStepEnd(MapView mapView, PlayerControl player) { + return false; } } diff --git a/src/mightypork/rogue/world/gui/interaction/MIPKeyWalk.java b/src/mightypork/rogue/world/gui/interaction/MIPKeyWalk.java index 14bb129..695fdd9 100644 --- a/src/mightypork/rogue/world/gui/interaction/MIPKeyWalk.java +++ b/src/mightypork/rogue/world/gui/interaction/MIPKeyWalk.java @@ -3,6 +3,8 @@ package mightypork.rogue.world.gui.interaction; import mightypork.gamecore.input.InputSystem; import mightypork.gamecore.input.Keys; +import mightypork.gamecore.util.math.algo.Sides; +import mightypork.gamecore.util.math.algo.Step; import mightypork.gamecore.util.math.constraints.vect.Vect; import mightypork.rogue.world.PlayerControl; import mightypork.rogue.world.gui.MapView; @@ -11,36 +13,51 @@ import mightypork.rogue.world.gui.MapView; public class MIPKeyWalk implements MapInteractionPlugin { @Override - public void onStepEnd(MapView view, PlayerControl player) + public boolean onStepEnd(MapView view, PlayerControl player) { - walkByKey(player); + return walkByKey(player); } @Override - public void onClick(MapView view, PlayerControl player, Vect mouse, int button, boolean down) + public boolean onClick(MapView view, PlayerControl player, Vect mouse, int button, boolean down) { + return false; } @Override - public void onKey(MapView view, PlayerControl player, int key, boolean down) + public boolean onKey(MapView view, PlayerControl player, int key, boolean down) { - if (down) walkByKey(player); + if (down) return walkByKey(player); + return false; } - private void walkByKey(PlayerControl player) + private boolean walkByKey(PlayerControl player) { - if (InputSystem.isKeyDown(Keys.LEFT)) { - player.goWest(); - } else if (InputSystem.isKeyDown(Keys.RIGHT)) { - player.goEast(); - } else if (InputSystem.isKeyDown(Keys.UP)) { - player.goNorth(); - } else if (InputSystem.isKeyDown(Keys.DOWN)) { - player.goSouth(); + final int[] keys = { Keys.LEFT, Keys.RIGHT, Keys.UP, Keys.DOWN }; + final Step[] sides = { Sides.W, Sides.E, Sides.N, Sides.S }; + + for (int i = 0; i < 4; i++) { + if (InputSystem.isKeyDown(keys[i])) { + + final Step side = sides[i]; + if (player.canGo(side)) { + player.go(side); + return true; + } else { + return player.clickTile(side); + } + + } } + return false; } + + @Override + public void update(MapView mapView, PlayerControl pc, double delta) + { + } } diff --git a/src/mightypork/rogue/world/gui/interaction/MIPMouseWalk.java b/src/mightypork/rogue/world/gui/interaction/MIPMouseWalk.java index 2cec069..0a291e3 100644 --- a/src/mightypork/rogue/world/gui/interaction/MIPMouseWalk.java +++ b/src/mightypork/rogue/world/gui/interaction/MIPMouseWalk.java @@ -8,12 +8,13 @@ import mightypork.gamecore.util.math.algo.Coord; import mightypork.gamecore.util.math.constraints.vect.Vect; import mightypork.rogue.world.PlayerControl; import mightypork.rogue.world.gui.MapView; +import mightypork.rogue.world.tile.Tile; public class MIPMouseWalk implements MapInteractionPlugin { @Override - public void onStepEnd(MapView world, PlayerControl player) + public void update(MapView world, PlayerControl player, double delta) { if (InputSystem.isMouseButtonDown(0)) { // walk by holding btn @@ -23,13 +24,15 @@ public class MIPMouseWalk implements MapInteractionPlugin { @Override - public void onClick(MapView world, PlayerControl player, Vect mouse, int button, boolean down) + public boolean onClick(MapView world, PlayerControl player, Vect mouse, int button, boolean down) { - if (!down) return; + if (!down || button != 0) return false; final Coord plpos = player.getCoord(); final Coord clicked = world.toWorldPos(mouse); + final Tile t = player.getLevel().getTile(clicked); + final Polar p = Polar.fromCoord(clicked.x - plpos.x, clicked.y - plpos.y); final int dir = Deg.round90(p.getAngleDeg()) / 90; @@ -37,26 +40,35 @@ public class MIPMouseWalk implements MapInteractionPlugin { switch (dir) { case 0: player.goEast(); - return; - + break; + case 1: player.goSouth(); - return; - + break; + case 2: player.goWest(); - return; - + break; + case 3: player.goNorth(); - return; + break; } + return true; + } + + + @Override + public boolean onKey(MapView world, PlayerControl player, int key, boolean down) + { + return false; } @Override - public void onKey(MapView world, PlayerControl player, int key, boolean down) + public boolean onStepEnd(MapView mapView, PlayerControl player) { + return false; } } diff --git a/src/mightypork/rogue/world/gui/interaction/MIPTileClick.java b/src/mightypork/rogue/world/gui/interaction/MIPTileClick.java new file mode 100644 index 0000000..64ff2f4 --- /dev/null +++ b/src/mightypork/rogue/world/gui/interaction/MIPTileClick.java @@ -0,0 +1,43 @@ +package mightypork.rogue.world.gui.interaction; + + +import mightypork.gamecore.util.math.algo.Coord; +import mightypork.gamecore.util.math.constraints.vect.Vect; +import mightypork.rogue.world.PlayerControl; +import mightypork.rogue.world.gui.MapView; + + +public class MIPTileClick implements MapInteractionPlugin { + + @Override + public boolean onStepEnd(MapView wv, PlayerControl player) + { + return false; + } + + + @Override + public boolean onClick(MapView wv, PlayerControl player, Vect mouse, int button, boolean down) + { + if (down && button == 1) { // right button + final Coord pos = wv.toWorldPos(mouse); + player.clickTile(pos); + return true; + } + + return false; + } + + + @Override + public boolean onKey(MapView wv, PlayerControl player, int key, boolean down) + { + return false; + } + + + @Override + public void update(MapView mapView, PlayerControl pc, double delta) + { + } +} diff --git a/src/mightypork/rogue/world/gui/interaction/MapInteractionPlugin.java b/src/mightypork/rogue/world/gui/interaction/MapInteractionPlugin.java index 588f257..041d290 100644 --- a/src/mightypork/rogue/world/gui/interaction/MapInteractionPlugin.java +++ b/src/mightypork/rogue/world/gui/interaction/MapInteractionPlugin.java @@ -8,12 +8,15 @@ import mightypork.rogue.world.gui.MapView; public interface MapInteractionPlugin { - void onStepEnd(MapView wv, PlayerControl player); + boolean onStepEnd(MapView mapView, PlayerControl player); - void onClick(MapView wv, PlayerControl player, Vect mouse, int button, boolean down); + boolean onClick(MapView mapView, PlayerControl player, Vect mouse, int button, boolean down); - void onKey(MapView wv, PlayerControl player, int key, boolean down); + boolean onKey(MapView mapView, PlayerControl player, int key, boolean down); + + + void update(MapView mapView, PlayerControl pc, double delta); } diff --git a/src/mightypork/rogue/world/level/render/TileRenderContext.java b/src/mightypork/rogue/world/level/render/TileRenderContext.java index 23c8ad1..5d2c2cf 100644 --- a/src/mightypork/rogue/world/level/render/TileRenderContext.java +++ b/src/mightypork/rogue/world/level/render/TileRenderContext.java @@ -25,7 +25,7 @@ public final class TileRenderContext extends MapRenderContext implements RectBou { super(map, drawArea); - //this.tiler.setOverlap(0.02); // avoid gaps (rounding error?) + //this.tiler.setOverlap(0.002); // avoid gaps (rounding error?) this.noise = map.getNoiseGen(); } diff --git a/src/mightypork/rogue/world/tile/Tile.java b/src/mightypork/rogue/world/tile/Tile.java index ca4cccb..b1aab25 100644 --- a/src/mightypork/rogue/world/tile/Tile.java +++ b/src/mightypork/rogue/world/tile/Tile.java @@ -2,6 +2,7 @@ package mightypork.rogue.world.tile; import java.io.IOException; +import java.util.Random; import mightypork.gamecore.util.annot.DefaultImpl; import mightypork.gamecore.util.ion.IonInput; @@ -24,6 +25,9 @@ public abstract class Tile implements IonObjBlob { public final TileRenderData renderData = new TileRenderData(); public final TileGenData genData = new TileGenData(); + /** RNG for random stuff in tiles */ + protected static final Random rand = new Random(); + protected final TileRenderer renderer; public final TileModel model; @@ -168,7 +172,7 @@ public abstract class Tile implements IonObjBlob { } - public final Color getMapColor() + public Color getMapColor() { return getType().getMapColor(); } @@ -202,4 +206,16 @@ public abstract class Tile implements IonObjBlob { */ public abstract boolean hasItem(); + + /** + * Handle player click + * + * @return true if the tile is interactive and did something. + */ + @DefaultImpl + public boolean onClick() + { + return false; + } + } diff --git a/src/mightypork/rogue/world/tile/TileGenData.java b/src/mightypork/rogue/world/tile/TileGenData.java index 1f1e4ad..1270596 100644 --- a/src/mightypork/rogue/world/tile/TileGenData.java +++ b/src/mightypork/rogue/world/tile/TileGenData.java @@ -1,6 +1,9 @@ package mightypork.rogue.world.tile; +import mightypork.rogue.world.gen.TileProtectLevel; + + /** * Data storage for world generator * @@ -8,6 +11,6 @@ package mightypork.rogue.world.tile; */ public class TileGenData { - public boolean isProtected = false; + public TileProtectLevel protection = TileProtectLevel.NONE; } diff --git a/src/mightypork/rogue/world/tile/TileRenderer.java b/src/mightypork/rogue/world/tile/TileRenderer.java index 179ceea..904daa9 100644 --- a/src/mightypork/rogue/world/tile/TileRenderer.java +++ b/src/mightypork/rogue/world/tile/TileRenderer.java @@ -72,16 +72,16 @@ public abstract class TileRenderer { if (trd.shadows == 0) return; final Rect rect = context.getRect(); - if ((trd.shadows & Sides.MASK_NW) != 0) Render.quadTextured(rect, SH_NW); + if ((trd.shadows & Sides.NW_CORNER) == Sides.MASK_NW) Render.quadTextured(rect, SH_NW); if ((trd.shadows & Sides.MASK_N) != 0) Render.quadTextured(rect, SH_N); - if ((trd.shadows & Sides.MASK_NE) != 0) Render.quadTextured(rect, SH_NE); + if ((trd.shadows & Sides.NE_CORNER) == Sides.MASK_NE) Render.quadTextured(rect, SH_NE); if ((trd.shadows & Sides.MASK_W) != 0) Render.quadTextured(rect, SH_W); if ((trd.shadows & Sides.MASK_E) != 0) Render.quadTextured(rect, SH_E); - if ((trd.shadows & Sides.MASK_SW) != 0) Render.quadTextured(rect, SH_SW); + if ((trd.shadows & Sides.SW_CORNER) == Sides.MASK_SW) Render.quadTextured(rect, SH_SW); if ((trd.shadows & Sides.MASK_S) != 0) Render.quadTextured(rect, SH_S); - if ((trd.shadows & Sides.MASK_SE) != 0) Render.quadTextured(rect, SH_SE); + if ((trd.shadows & Sides.SE_CORNER) == Sides.MASK_SE) Render.quadTextured(rect, SH_SE); } diff --git a/src/mightypork/rogue/world/tile/Tiles.java b/src/mightypork/rogue/world/tile/Tiles.java index 0d2786b..96d14a8 100644 --- a/src/mightypork/rogue/world/tile/Tiles.java +++ b/src/mightypork/rogue/world/tile/Tiles.java @@ -6,13 +6,10 @@ import java.io.IOException; import mightypork.gamecore.util.ion.IonInput; import mightypork.gamecore.util.ion.IonOutput; import mightypork.rogue.world.tile.renderers.BasicTileRenderer; -import mightypork.rogue.world.tile.renderers.DoorTileRenderer; +import mightypork.rogue.world.tile.renderers.DoorRenderer; +import mightypork.rogue.world.tile.renderers.LockedDoorRenderer; import mightypork.rogue.world.tile.renderers.NullTileRenderer; -import mightypork.rogue.world.tile.tiles.DoorTile; -import mightypork.rogue.world.tile.tiles.FloorTile; -import mightypork.rogue.world.tile.tiles.NullTile; -import mightypork.rogue.world.tile.tiles.WallPassageTile; -import mightypork.rogue.world.tile.tiles.WallTile; +import mightypork.rogue.world.tile.tiles.*; /** @@ -28,8 +25,10 @@ public final class Tiles { public static final TileModel BRICK_FLOOR = new TileModel(10, FloorTile.class, new BasicTileRenderer("tile.brick.floor")); public static final TileModel BRICK_WALL = new TileModel(11, WallTile.class, new BasicTileRenderer("tile.brick.wall")); - public static final TileModel BRICK_DOOR = new TileModel(12, DoorTile.class, new DoorTileRenderer("tile.brick.door.closed", "tile.brick.door.open")); + public static final TileModel BRICK_DOOR = new TileModel(12, DoorTile.class, new DoorRenderer("tile.brick.door.closed", "tile.brick.door.open")); public static final TileModel BRICK_PASSAGE = new TileModel(13, WallPassageTile.class, new BasicTileRenderer("tile.brick.passage")); + public static final TileModel BRICK_HIDDEN_DOOR = new TileModel(14, SecretDoorTile.class, new LockedDoorRenderer("tile.brick.door.secret", + "tile.brick.door.closed", "tile.brick.door.open")); public static void register(int id, TileModel model) diff --git a/src/mightypork/rogue/world/tile/renderers/DoorTileRenderer.java b/src/mightypork/rogue/world/tile/renderers/DoorRenderer.java similarity index 88% rename from src/mightypork/rogue/world/tile/renderers/DoorTileRenderer.java rename to src/mightypork/rogue/world/tile/renderers/DoorRenderer.java index a009582..9d3bbb1 100644 --- a/src/mightypork/rogue/world/tile/renderers/DoorTileRenderer.java +++ b/src/mightypork/rogue/world/tile/renderers/DoorRenderer.java @@ -10,13 +10,13 @@ import mightypork.rogue.world.tile.Tile; import mightypork.rogue.world.tile.TileRenderer; -public class DoorTileRenderer extends TileRenderer { +public class DoorRenderer extends TileRenderer { private final TxSheet closed; private final TxSheet open; - public DoorTileRenderer(String quadClosed, String quadOpen) + public DoorRenderer(String quadClosed, String quadOpen) { this.closed = Res.getTxSheet(quadClosed); this.open = Res.getTxSheet(quadOpen); diff --git a/src/mightypork/rogue/world/tile/renderers/LockedDoorRenderer.java b/src/mightypork/rogue/world/tile/renderers/LockedDoorRenderer.java new file mode 100644 index 0000000..7846a55 --- /dev/null +++ b/src/mightypork/rogue/world/tile/renderers/LockedDoorRenderer.java @@ -0,0 +1,37 @@ +package mightypork.rogue.world.tile.renderers; + + +import mightypork.gamecore.render.Render; +import mightypork.gamecore.resources.textures.TxSheet; +import mightypork.gamecore.util.math.constraints.rect.Rect; +import mightypork.rogue.Res; +import mightypork.rogue.world.level.render.TileRenderContext; +import mightypork.rogue.world.tile.Tile; + + +public class LockedDoorRenderer extends DoorRenderer { + + private final TxSheet locked; + + + public LockedDoorRenderer(String sheetLocked, String sheetClosed, String sheetOpen) + { + super(sheetClosed, sheetOpen); + this.locked = Res.getTxSheet(sheetLocked); + } + + + @Override + public void renderTile(TileRenderContext context) + { + final Tile t = context.getTile(); + + if (!t.isWalkable()) { + final Rect rect = context.getRect(); + Render.quadTextured(rect, locked.getRandomQuad(context.getTileNoise())); + } else { + super.renderTile(context); + } + } + +} diff --git a/src/mightypork/rogue/world/tile/tiles/SecretDoorTile.java b/src/mightypork/rogue/world/tile/tiles/SecretDoorTile.java new file mode 100644 index 0000000..ee28f47 --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/SecretDoorTile.java @@ -0,0 +1,35 @@ +package mightypork.rogue.world.tile.tiles; + + +import mightypork.gamecore.util.math.color.Color; +import mightypork.rogue.world.tile.TileModel; +import mightypork.rogue.world.tile.TileRenderer; +import mightypork.rogue.world.tile.TileType; + + +public class SecretDoorTile extends LockedDoorTile { + + public SecretDoorTile(TileModel model, TileRenderer renderer) + { + super(model, renderer); + } + + + @Override + public boolean onClick() + { + if (!locked) return false; + + locked = false; + + return true; + } + + + @Override + public Color getMapColor() + { + if (locked) return TileType.WALL.getMapColor(); + return super.getMapColor(); + } +}