From fb244dc2b9412520223add77d53aab6609981c61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Thu, 1 May 2014 13:49:49 +0200 Subject: [PATCH] first monster, remade tile renderer system etc --- .../gamecore/util/math/algo/Sides.java | 10 +- .../math/algo/pathfinding/PathFinder.java | 106 +++++-- ...ContextProxy.java => PathFinderProxy.java} | 12 +- .../algo/pathfinding/PathFindingContext.java | 40 --- .../gamecore/util/math/timing/Animator.java | 2 +- .../gamecore/util/math/timing/TimedTask.java | 5 + src/mightypork/rogue/App.java | 2 +- src/mightypork/rogue/Res.java | 5 +- src/mightypork/rogue/world/World.java | 4 +- src/mightypork/rogue/world/WorldCreator.java | 2 +- src/mightypork/rogue/world/WorldRenderer.java | 2 +- .../rogue/world/entity/Entities.java | 2 + src/mightypork/rogue/world/entity/Entity.java | 22 +- .../rogue/world/entity/EntityModel.java | 5 + ...dingContext.java => EntityPathFinder.java} | 15 +- .../SimpleEntityPathFindingContext.java | 29 -- .../world/entity/entities/MonsterAi.java | 286 +++++++++++++----- .../world/entity/entities/PlayerEntity.java | 24 +- .../rogue/world/entity/entities/RatAi.java | 59 ++++ .../world/entity/entities/RatEntity.java | 59 ++++ .../world/entity/entities/SimpleMonster.java | 41 --- .../entity/modules/EntityModuleHealth.java | 6 + .../entity/modules/EntityModulePosition.java | 8 +- .../entity/renderers/EntityRenderer.java | 11 +- .../entity/renderers/EntityRendererMobLR.java | 6 +- .../rogue/world/gen/LevelGenerator.java | 21 +- .../rogue/world/gen/ScratchMap.java | 17 +- .../world/gen/rooms/AbstractRectRoom.java | 2 +- src/mightypork/rogue/world/gui/MapView.java | 2 +- src/mightypork/rogue/world/level/Level.java | 23 +- src/mightypork/rogue/world/tile/Tile.java | 23 +- .../rogue/world/tile/TileModel.java | 10 +- .../rogue/world/tile/TileRenderData.java | 14 - .../rogue/world/tile/TileRenderer.java | 64 ++-- src/mightypork/rogue/world/tile/Tiles.java | 20 +- .../tile/renderers/BasicTileRenderer.java | 7 +- .../world/tile/renderers/DoorRenderer.java | 39 --- .../tile/renderers/DoorTileRenderer.java | 70 +++++ .../tile/renderers/LockedDoorRenderer.java | 38 --- .../tile/renderers/NullTileRenderer.java | 30 ++ .../rogue/world/tile/tiles/DoorTile.java | 29 -- .../rogue/world/tile/tiles/FloorTile.java | 22 -- .../world/tile/tiles/LockedDoorTile.java | 44 --- .../rogue/world/tile/tiles/NullTile.java | 10 +- .../rogue/world/tile/tiles/TileBaseDoor.java | 82 +++++ .../rogue/world/tile/tiles/TileBaseFloor.java | 34 +++ .../world/tile/tiles/TileBasePassage.java | 49 +++ ...tDoorTile.java => TileBaseSecretDoor.java} | 11 +- .../rogue/world/tile/tiles/TileBaseWall.java | 35 +++ .../tiles/{SolidTile.java => TileSolid.java} | 6 +- .../{GroundTile.java => TileWalkable.java} | 7 +- .../world/tile/tiles/WallPassageTile.java | 35 --- .../rogue/world/tile/tiles/WallTile.java | 22 -- .../world/tile/tiles/brick/TileBrickDoor.java | 22 ++ .../tile/tiles/brick/TileBrickFloor.java | 16 + .../tile/tiles/brick/TileBrickPassage.java | 17 ++ .../tile/tiles/brick/TileBrickSecretDoor.java | 26 ++ .../world/tile/tiles/brick/TileBrickWall.java | 16 + 58 files changed, 1043 insertions(+), 583 deletions(-) rename src/mightypork/gamecore/util/math/algo/pathfinding/{PathFindingContextProxy.java => PathFinderProxy.java} (67%) delete mode 100644 src/mightypork/gamecore/util/math/algo/pathfinding/PathFindingContext.java rename src/mightypork/rogue/world/entity/{EntityPathfindingContext.java => EntityPathFinder.java} (67%) delete mode 100644 src/mightypork/rogue/world/entity/SimpleEntityPathFindingContext.java create mode 100644 src/mightypork/rogue/world/entity/entities/RatAi.java create mode 100644 src/mightypork/rogue/world/entity/entities/RatEntity.java delete mode 100644 src/mightypork/rogue/world/entity/entities/SimpleMonster.java delete mode 100644 src/mightypork/rogue/world/tile/TileRenderData.java delete mode 100644 src/mightypork/rogue/world/tile/renderers/DoorRenderer.java create mode 100644 src/mightypork/rogue/world/tile/renderers/DoorTileRenderer.java delete mode 100644 src/mightypork/rogue/world/tile/renderers/LockedDoorRenderer.java delete mode 100644 src/mightypork/rogue/world/tile/tiles/DoorTile.java delete mode 100644 src/mightypork/rogue/world/tile/tiles/FloorTile.java delete mode 100644 src/mightypork/rogue/world/tile/tiles/LockedDoorTile.java create mode 100644 src/mightypork/rogue/world/tile/tiles/TileBaseDoor.java create mode 100644 src/mightypork/rogue/world/tile/tiles/TileBaseFloor.java create mode 100644 src/mightypork/rogue/world/tile/tiles/TileBasePassage.java rename src/mightypork/rogue/world/tile/tiles/{SecretDoorTile.java => TileBaseSecretDoor.java} (72%) create mode 100644 src/mightypork/rogue/world/tile/tiles/TileBaseWall.java rename src/mightypork/rogue/world/tile/tiles/{SolidTile.java => TileSolid.java} (81%) rename src/mightypork/rogue/world/tile/tiles/{GroundTile.java => TileWalkable.java} (92%) delete mode 100644 src/mightypork/rogue/world/tile/tiles/WallPassageTile.java delete mode 100644 src/mightypork/rogue/world/tile/tiles/WallTile.java create mode 100644 src/mightypork/rogue/world/tile/tiles/brick/TileBrickDoor.java create mode 100644 src/mightypork/rogue/world/tile/tiles/brick/TileBrickFloor.java create mode 100644 src/mightypork/rogue/world/tile/tiles/brick/TileBrickPassage.java create mode 100644 src/mightypork/rogue/world/tile/tiles/brick/TileBrickSecretDoor.java create mode 100644 src/mightypork/rogue/world/tile/tiles/brick/TileBrickWall.java diff --git a/src/mightypork/gamecore/util/math/algo/Sides.java b/src/mightypork/gamecore/util/math/algo/Sides.java index a0442d3..93e773f 100644 --- a/src/mightypork/gamecore/util/math/algo/Sides.java +++ b/src/mightypork/gamecore/util/math/algo/Sides.java @@ -12,8 +12,8 @@ public class Sides { public static final byte MASK_SW = (byte) 0b00000010; public static final byte MASK_W = (byte) 0b00000001; - public static final byte CARDINAL = MASK_N | MASK_S | MASK_E | MASK_W; - public static final byte DIAGONAL = MASK_NE | MASK_NW | MASK_SE | MASK_SW; + 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; @@ -31,7 +31,7 @@ public class Sides { //@formatter:off /** All sides, in the order of bits. */ - public final static Step[] allSides = { + public final static Step[] ALL_SIDES = { NW, N, NE, @@ -42,7 +42,7 @@ public class Sides { W }; - public final static Step[] cardinalSides = { + public final static Step[] CARDINAL_SIDES = { N, E, S, @@ -59,7 +59,7 @@ public class Sides { */ public static Step get(int i) { - return allSides[i]; + return ALL_SIDES[i]; } diff --git a/src/mightypork/gamecore/util/math/algo/pathfinding/PathFinder.java b/src/mightypork/gamecore/util/math/algo/pathfinding/PathFinder.java index 0ae33cd..83d9092 100644 --- a/src/mightypork/gamecore/util/math/algo/pathfinding/PathFinder.java +++ b/src/mightypork/gamecore/util/math/algo/pathfinding/PathFinder.java @@ -18,7 +18,7 @@ import mightypork.gamecore.util.math.algo.pathfinding.heuristics.ManhattanHeuris * * @author MightyPork */ -public class PathFinder { +public abstract class PathFinder { private static final FComparator F_COMPARATOR = new FComparator(); @@ -26,9 +26,15 @@ public class PathFinder { public static final Heuristic DIAGONAL_HEURISTIC = new DiagonalHeuristic(); - public static List findPathRelative(PathFindingContext context, Coord start, Coord end) + public List findPathRelative(Coord start, Coord end) { - final List path = findPath(context, start, end); + return findPathRelative(start, end, false); + } + + + public List findPathRelative(Coord start, Coord end, boolean ignoreEnd) + { + final List path = findPath(start, end, ignoreEnd); if (path == null) return null; final List out = new ArrayList<>(); @@ -45,22 +51,28 @@ public class PathFinder { } - public static List findPath(PathFindingContext context, Coord start, Coord end) + public List findPath(Coord start, Coord end) + { + return findPath(start, end, false); + } + + + public List findPath(Coord start, Coord end, boolean ignoreEnd) { final LinkedList open = new LinkedList<>(); final LinkedList closed = new LinkedList<>(); - final Heuristic heuristic = context.getHeuristic(); + final Heuristic heuristic = getHeuristic(); // add first node { final Node n = new Node(start); - n.h_cost = (int) (heuristic.getCost(start, end) * context.getMinCost()); + n.h_cost = (int) (heuristic.getCost(start, end) * getMinCost()); n.g_cost = 0; open.add(n); } - final Step[] walkDirs = context.getWalkSides(); + final Step[] walkDirs = getWalkSides(); Node current = null; @@ -80,43 +92,43 @@ public class PathFinder { for (final Step go : walkDirs) { final Coord c = current.pos.add(go); - if (!context.isAccessible(c)) continue; + if (!isAccessible(c) && !(c.equals(end) && ignoreEnd)) continue; final Node a = new Node(c); - a.g_cost = current.g_cost + context.getCost(c, a.pos); - a.h_cost = (int) (heuristic.getCost(a.pos, end) * context.getMinCost()); + a.g_cost = current.g_cost + getCost(c, a.pos); + a.h_cost = (int) (heuristic.getCost(a.pos, end) * getMinCost()); a.parent = current; - if (context.isAccessible(a.pos)) { - if (!closed.contains(a)) { + + if (!closed.contains(a)) { + + if (open.contains(a)) { - if (open.contains(a)) { - - boolean needSort = false; - - // find where it is - for (final Node n : open) { - if (n.pos.equals(a.pos)) { // found it - if (n.g_cost > a.g_cost) { - n.parent = current; - n.g_cost = a.g_cost; - needSort = true; - } - break; + boolean needSort = false; + + // find where it is + for (final Node n : open) { + if (n.pos.equals(a.pos)) { // found it + if (n.g_cost > a.g_cost) { + n.parent = current; + n.g_cost = a.g_cost; + needSort = true; } + break; } - - if (needSort) Collections.sort(open, F_COMPARATOR); - - } else { - open.add(a); } + + if (needSort) Collections.sort(open, F_COMPARATOR); + + } else { + open.add(a); } } } } - if (current == null) { return null; // no path found + if (current == null) { + return null; // no path found } final LinkedList path = new LinkedList<>(); @@ -189,4 +201,36 @@ public class PathFinder { return n1.fCost() - n2.fCost(); } } + + + /** + * @return used heuristic + */ + protected abstract Heuristic getHeuristic(); + + + protected abstract Step[] getWalkSides(); + + + /** + * @param pos tile pos + * @return true if the tile is walkable + */ + protected abstract boolean isAccessible(Coord pos); + + + /** + * Cost of walking onto a tile. It's useful to use ie. 10 for basic step. + * + * @param from last tile + * @param to current tile + * @return cost + */ + protected abstract int getCost(Coord from, Coord to); + + + /** + * @return lowest cost. Used to multiply heuristics. + */ + protected abstract int getMinCost(); } diff --git a/src/mightypork/gamecore/util/math/algo/pathfinding/PathFindingContextProxy.java b/src/mightypork/gamecore/util/math/algo/pathfinding/PathFinderProxy.java similarity index 67% rename from src/mightypork/gamecore/util/math/algo/pathfinding/PathFindingContextProxy.java rename to src/mightypork/gamecore/util/math/algo/pathfinding/PathFinderProxy.java index 6ec31da..6012c9e 100644 --- a/src/mightypork/gamecore/util/math/algo/pathfinding/PathFindingContextProxy.java +++ b/src/mightypork/gamecore/util/math/algo/pathfinding/PathFinderProxy.java @@ -6,17 +6,17 @@ import mightypork.gamecore.util.math.algo.Step; /** - * Pathfinding context proxy. Can be used to override individual methods but + * Pathfinder proxy. Can be used to override individual methods but * keep the rest as is. * * @author MightyPork */ -public class PathFindingContextProxy implements PathFindingContext { +public class PathFinderProxy extends PathFinder { - private final PathFindingContext source; + private final PathFinder source; - public PathFindingContextProxy(PathFindingContext other) + public PathFinderProxy(PathFinder other) { this.source = other; } @@ -44,14 +44,14 @@ public class PathFindingContextProxy implements PathFindingContext { @Override - public Heuristic getHeuristic() + protected Heuristic getHeuristic() { return source.getHeuristic(); } @Override - public Step[] getWalkSides() + protected Step[] getWalkSides() { return source.getWalkSides(); } diff --git a/src/mightypork/gamecore/util/math/algo/pathfinding/PathFindingContext.java b/src/mightypork/gamecore/util/math/algo/pathfinding/PathFindingContext.java deleted file mode 100644 index 79fa034..0000000 --- a/src/mightypork/gamecore/util/math/algo/pathfinding/PathFindingContext.java +++ /dev/null @@ -1,40 +0,0 @@ -package mightypork.gamecore.util.math.algo.pathfinding; - - -import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.Step; - - -public interface PathFindingContext { - - /** - * @param pos tile pos - * @return true if the tile is walkable - */ - boolean isAccessible(Coord pos); - - - /** - * Cost of walking onto a tile. It's useful to use ie. 10 for basic step. - * - * @param from last tile - * @param to current tile - * @return cost - */ - int getCost(Coord from, Coord to); - - - /** - * @return lowest cost. Used to multiply heuristics. - */ - int getMinCost(); - - - /** - * @return used heuristic - */ - Heuristic getHeuristic(); - - - Step[] getWalkSides(); -} diff --git a/src/mightypork/gamecore/util/math/timing/Animator.java b/src/mightypork/gamecore/util/math/timing/Animator.java index 670d342..a0c2924 100644 --- a/src/mightypork/gamecore/util/math/timing/Animator.java +++ b/src/mightypork/gamecore/util/math/timing/Animator.java @@ -83,7 +83,7 @@ public abstract class Animator extends Num implements Updateable, Pauseable { public void restart() { reset(); - nextCycle(numAnim); + resume(); } diff --git a/src/mightypork/gamecore/util/math/timing/TimedTask.java b/src/mightypork/gamecore/util/math/timing/TimedTask.java index 1e71623..fd0e44c 100644 --- a/src/mightypork/gamecore/util/math/timing/TimedTask.java +++ b/src/mightypork/gamecore/util/math/timing/TimedTask.java @@ -29,6 +29,11 @@ public abstract class TimedTask implements Runnable, Updateable { } + public boolean isRunning() { + return !timer.isFinished(); + } + + public void start(double seconds) { timer.reset(); diff --git a/src/mightypork/rogue/App.java b/src/mightypork/rogue/App.java index e0b776e..05dd26c 100644 --- a/src/mightypork/rogue/App.java +++ b/src/mightypork/rogue/App.java @@ -162,6 +162,6 @@ public final class App extends BaseApp { // TODO tmp WorldProvider.get().createWorld(Double.doubleToLongBits(Math.random())); - getEventBus().send(new CrossfadeRequest("menu", true)); + getEventBus().send(new CrossfadeRequest("game", true)); } } diff --git a/src/mightypork/rogue/Res.java b/src/mightypork/rogue/Res.java index e69b56a..6d07161 100644 --- a/src/mightypork/rogue/Res.java +++ b/src/mightypork/rogue/Res.java @@ -86,7 +86,8 @@ public final class Res { textures.addSheet("tile.brick.floor", tiles.makeSheet(0, 1, 5, 1)); textures.addSheet("tile.brick.wall", tiles.makeSheet(0, 0, 8, 1)); - + + textures.addSheet("tile.brick.door.locked", tiles.makeSheet(1, 2, 1, 1));//TODO unique tx 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)); @@ -134,7 +135,7 @@ public final class Res { } - public static TxSheet getTxSheet(String key) + public static TxSheet sheet(String key) { return textures.getSheet(key); } diff --git a/src/mightypork/rogue/world/World.java b/src/mightypork/rogue/world/World.java index 7f4eb2d..3330807 100644 --- a/src/mightypork/rogue/world/World.java +++ b/src/mightypork/rogue/world/World.java @@ -9,6 +9,7 @@ import mightypork.gamecore.util.ion.IonBundle; import mightypork.gamecore.util.ion.IonObjBundled; import mightypork.rogue.world.entity.Entities; import mightypork.rogue.world.entity.Entity; +import mightypork.rogue.world.entity.EntityModel; import mightypork.rogue.world.level.Level; @@ -94,7 +95,6 @@ public class World implements IonObjBundled, Updateable { return eid++; } - public void createPlayer(int level) { if (playerInfo.isInitialized()) { throw new RuntimeException("Player already created."); } @@ -103,7 +103,7 @@ public class World implements IonObjBundled, Updateable { final int playerEid = getNewEID(); playerEntity = Entities.PLAYER.createEntity(playerEid); - playerEntity.pos.setPosition(levels.get(level).getEnterPoint()); + playerEntity.setCoord(levels.get(level).getEnterPoint()); levels.get(level).addEntity(playerEntity); playerInfo.setLevel(level); diff --git a/src/mightypork/rogue/world/WorldCreator.java b/src/mightypork/rogue/world/WorldCreator.java index c2672fc..4ffa354 100644 --- a/src/mightypork/rogue/world/WorldCreator.java +++ b/src/mightypork/rogue/world/WorldCreator.java @@ -25,7 +25,7 @@ public class WorldCreator { // TODO real algorithm // first level - l = LevelGenerator.build(rand.nextLong(), 6, LevelGenerator.DUNGEON_THEME); // + l = LevelGenerator.build(w, rand.nextLong(), 1, LevelGenerator.DUNGEON_THEME); // w.addLevel(l); w.createPlayer(0); diff --git a/src/mightypork/rogue/world/WorldRenderer.java b/src/mightypork/rogue/world/WorldRenderer.java index 01b00c4..35779d6 100644 --- a/src/mightypork/rogue/world/WorldRenderer.java +++ b/src/mightypork/rogue/world/WorldRenderer.java @@ -89,7 +89,7 @@ public class WorldRenderer extends RectProxy { // tiles to render final Entity ent = WorldProvider.get().getPlayerEntity(); - final Coord pos = ent.pos.getCoord(); + final Coord pos = ent.getCoord(); final double w = width().value(); final double h = height().value(); diff --git a/src/mightypork/rogue/world/entity/Entities.java b/src/mightypork/rogue/world/entity/Entities.java index e43e04f..c728bfc 100644 --- a/src/mightypork/rogue/world/entity/Entities.java +++ b/src/mightypork/rogue/world/entity/Entities.java @@ -7,6 +7,7 @@ import java.util.Collection; import mightypork.gamecore.util.ion.IonInput; import mightypork.gamecore.util.ion.IonOutput; import mightypork.rogue.world.entity.entities.PlayerEntity; +import mightypork.rogue.world.entity.entities.RatEntity; /** @@ -19,6 +20,7 @@ public final class Entities { private static final EntityModel[] entities = new EntityModel[256]; public static final EntityModel PLAYER = new EntityModel(1, PlayerEntity.class); + public static final EntityModel RAT = new EntityModel(2, RatEntity.class); public static void register(int id, EntityModel model) diff --git a/src/mightypork/rogue/world/entity/Entity.java b/src/mightypork/rogue/world/entity/Entity.java index 0384a75..3365901 100644 --- a/src/mightypork/rogue/world/entity/Entity.java +++ b/src/mightypork/rogue/world/entity/Entity.java @@ -12,7 +12,7 @@ import mightypork.gamecore.util.error.IllegalValueException; import mightypork.gamecore.util.ion.IonBundle; import mightypork.gamecore.util.ion.IonObjBundled; import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.pathfinding.PathFindingContext; +import mightypork.gamecore.util.math.algo.pathfinding.PathFinder; import mightypork.rogue.world.World; import mightypork.rogue.world.entity.modules.EntityModuleHealth; import mightypork.rogue.world.entity.modules.EntityModulePosition; @@ -101,7 +101,9 @@ public abstract class Entity implements IonObjBundled, Updateable { protected final void addModule(String key, EntityModule module) { - if (modules.containsKey(key)) { throw new RuntimeException("Entity module " + key + " already defined."); } + if (modules.containsKey(key)) { + throw new RuntimeException("Entity module " + key + " already defined."); + } modules.put(key, module); } @@ -117,7 +119,11 @@ public abstract class Entity implements IonObjBundled, Updateable { public void setLevel(Level level) { + if (level != null) level.freeTile(getCoord()); + this.level = level; + + if (level != null) level.occupyTile(getCoord()); } @@ -139,7 +145,7 @@ public abstract class Entity implements IonObjBundled, Updateable { } - public abstract PathFindingContext getPathfindingContext(); + public abstract PathFinder getPathFinder(); @DefaultImpl @@ -176,6 +182,16 @@ public abstract class Entity implements IonObjBundled, Updateable { } + public void setCoord(Coord coord) + { + if (level != null) level.freeTile(getCoord()); + + pos.setCoord(coord); + + if (level != null) level.occupyTile(getCoord()); + } + + /** * Called right after the entity's health reaches zero. */ diff --git a/src/mightypork/rogue/world/entity/EntityModel.java b/src/mightypork/rogue/world/entity/EntityModel.java index d9fda59..2119d21 100644 --- a/src/mightypork/rogue/world/entity/EntityModel.java +++ b/src/mightypork/rogue/world/entity/EntityModel.java @@ -6,6 +6,7 @@ import java.io.IOException; import mightypork.gamecore.util.ion.IonBundle; import mightypork.gamecore.util.ion.IonInput; import mightypork.gamecore.util.ion.IonOutput; +import mightypork.rogue.world.World; /** @@ -27,6 +28,10 @@ public final class EntityModel { this.tileClass = entity; } + public Entity createEntity(World world) + { + return createEntity(world.getNewEID()); + } public Entity createEntity(int eid) { diff --git a/src/mightypork/rogue/world/entity/EntityPathfindingContext.java b/src/mightypork/rogue/world/entity/EntityPathFinder.java similarity index 67% rename from src/mightypork/rogue/world/entity/EntityPathfindingContext.java rename to src/mightypork/rogue/world/entity/EntityPathFinder.java index 125224f..9714823 100644 --- a/src/mightypork/rogue/world/entity/EntityPathfindingContext.java +++ b/src/mightypork/rogue/world/entity/EntityPathFinder.java @@ -6,15 +6,14 @@ import mightypork.gamecore.util.math.algo.Sides; import mightypork.gamecore.util.math.algo.Step; import mightypork.gamecore.util.math.algo.pathfinding.Heuristic; import mightypork.gamecore.util.math.algo.pathfinding.PathFinder; -import mightypork.gamecore.util.math.algo.pathfinding.PathFindingContext; -public abstract class EntityPathfindingContext implements PathFindingContext { +public class EntityPathFinder extends PathFinder { protected final Entity entity; - public EntityPathfindingContext(Entity entity) + public EntityPathFinder(Entity entity) { this.entity = entity; } @@ -28,11 +27,15 @@ public abstract class EntityPathfindingContext implements PathFindingContext { @Override - public abstract int getCost(Coord from, Coord to); + public int getCost(Coord from, Coord to) { + return 10; + } @Override - public abstract int getMinCost(); + public int getMinCost() { + return 10; + } @Override @@ -45,7 +48,7 @@ public abstract class EntityPathfindingContext implements PathFindingContext { @Override public Step[] getWalkSides() { - return Sides.cardinalSides; + return Sides.CARDINAL_SIDES; } } diff --git a/src/mightypork/rogue/world/entity/SimpleEntityPathFindingContext.java b/src/mightypork/rogue/world/entity/SimpleEntityPathFindingContext.java deleted file mode 100644 index 0ce6edf..0000000 --- a/src/mightypork/rogue/world/entity/SimpleEntityPathFindingContext.java +++ /dev/null @@ -1,29 +0,0 @@ -package mightypork.rogue.world.entity; - - -import mightypork.gamecore.util.math.algo.Coord; - - -public class SimpleEntityPathFindingContext extends EntityPathfindingContext { - - public SimpleEntityPathFindingContext(Entity entity) - { - super(entity); - } - - - @Override - public int getCost(Coord from, Coord to) - { - return 10; - } - - - @Override - public int getMinCost() - { - return 10; - } - - -} diff --git a/src/mightypork/rogue/world/entity/entities/MonsterAi.java b/src/mightypork/rogue/world/entity/entities/MonsterAi.java index df0de46..0ffca59 100644 --- a/src/mightypork/rogue/world/entity/entities/MonsterAi.java +++ b/src/mightypork/rogue/world/entity/entities/MonsterAi.java @@ -9,8 +9,7 @@ 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.pathfinding.PathFinder; -import mightypork.gamecore.util.math.algo.pathfinding.PathFindingContext; -import mightypork.gamecore.util.math.algo.pathfinding.PathFindingContextProxy; +import mightypork.gamecore.util.math.algo.pathfinding.PathFinderProxy; import mightypork.rogue.world.entity.AiTimer; import mightypork.rogue.world.entity.Entity; import mightypork.rogue.world.entity.EntityModule; @@ -29,7 +28,8 @@ public class MonsterAi extends EntityModule implements EntityMoveListener { @Override public void run() { - System.out.println("Mob looks around."); + if (chasing) return; + //System.out.println("Mob looks around."); lookForTarget(); } }; @@ -39,21 +39,42 @@ public class MonsterAi extends EntityModule implements EntityMoveListener { @Override public void run() { - System.out.println("Mob going to sleep"); + if (chasing) return; + //System.out.println("Mob going to sleep"); sleeping = true; } }; - private PathFindingContext pathfcNoDoor; + private final AiTimer timerAttack = new AiTimer(3) { + + @Override + public void run() + { + if (!chasing) return; + + Entity prey = getPreyEntity(); + + if (prey == null || prey.isDead()) { + //System.out.println("prey dead?"); + return; + } + + //System.out.println("Timed prey attack"); + attackPrey(prey); + } + }; + + private PathFinder noDoorPf; - private int targetId = -1; + /** Prey id */ + private int preyId = -1; public MonsterAi(final Entity entity) { super(entity); - pathfcNoDoor = new PathFindingContextProxy(entity.getPathfindingContext()) { + noDoorPf = new PathFinderProxy(entity.getPathFinder()) { @Override public boolean isAccessible(Coord pos) @@ -65,32 +86,164 @@ public class MonsterAi extends EntityModule implements EntityMoveListener { } }; + + timerAttack.start(); + timerFindPrey.start(); + timerSleepStart.start(); + } + + + @Override + public void onStepFinished() + { + //System.out.println("monster ai step finished."); + if (chasing) { + //System.out.println("chasing.."); + final Entity prey = getPreyEntity(); + if (!isPreyValid(prey)) { + //System.out.println("prey dead or null, stop chasing: " + prey + ", prey.isdead " + prey.isDead()); + stopChasing(); + return; + } + + if (shouldRandomlyAbandonPrey()) { + stopChasing(); + return; + } + + if (isPreyInAttackRange(prey)) { + //System.out.println("prey in attack range"); + return; // attacking + } else { + stepTowardsPrey(prey); + } + } else { + //System.out.println("not chasing."); + } + } + + + @Override + public void onPathFinished() + { + } + + + @Override + public void onPathInterrupted() + { + } + + + @Override + public void save(IonBundle bundle) throws IOException + { + bundle.putBundled("tscan", timerFindPrey); + bundle.putBundled("tsleep", timerSleepStart); + bundle.putBundled("tattack", timerAttack); + + bundle.put("chasing", chasing); + bundle.put("sleeping", sleeping); + + bundle.put("prey", preyId); + } + + + @Override + public void load(IonBundle bundle) throws IOException + { + bundle.loadBundled("tscan", timerFindPrey); + bundle.loadBundled("tsleep", timerSleepStart); + bundle.loadBundled("tattack", timerAttack); + + chasing = bundle.get("chasing", chasing); + sleeping = bundle.get("sleeping", sleeping); + + preyId = bundle.get("prey", preyId); + } + + + @Override + public boolean isModuleSaved() + { + return true; + } + + + @Override + public void update(double delta) + { + timerFindPrey.update(delta); + timerSleepStart.update(delta); + timerAttack.update(delta); + + if (chasing && !entity.pos.isMoving()) { + Entity prey = getPreyEntity(); + + if (!isPreyInAttackRange(prey)) { + //System.out.println("-upd STEP--"); + stepTowardsPrey(prey); + } + } + } + + + public boolean isSleeping() + { + return sleeping; } private void lookForTarget() { - if (rand.nextInt(3) == 0) return; // not hungry right now + if (shouldSkipScan()) return; // not hungry right now + + //System.out.println("- Lookin for prey, r=" + getScanRadius()); final Entity prey = entity.getLevel().getClosestEntity(entity, EntityType.PLAYER, getScanRadius()); if (prey != null) { + //System.out.println("-- Prey in sight: " + prey); + //System.out.println("-- path would be: " + entity.getCoord() + "->" + prey.getCoord()); // check if reachable without leaving room - final List noDoorPath = PathFinder.findPath(pathfcNoDoor, entity.getCoord(), prey.getCoord()); + final List noDoorPath = noDoorPf.findPath(entity.getCoord(), prey.getCoord(), true); - if (noDoorPath == null) { return; // cant reach, give up + if (noDoorPath == null) { + //System.out.println("-- Could not navigate to prey, aborting."); + return; // cant reach, give up } startChasing(prey); + } else { + //System.out.println("-- Prey is null."); } + + } + + + private Entity getPreyEntity() + { + return entity.getLevel().getEntity(preyId); + } + + + private boolean isPreyInAttackRange(Entity prey) + { + return prey.getCoord().dist(entity.getCoord()) <= getAttackDistance(); + } + + + private boolean isPreyValid(Entity prey) + { + return prey != null && !prey.isDead(); } private void startChasing(Entity prey) { - // TODO if too close, attack directly + //System.out.println("start chasing"); - targetId = prey.getEntityId(); + preyId = prey.getEntityId(); chasing = true; sleeping = false; @@ -106,8 +259,9 @@ public class MonsterAi extends EntityModule implements EntityMoveListener { private void stopChasing() { + //System.out.println("stop chasing."); chasing = false; - targetId = -1; + preyId = -1; timerSleepStart.restart(); timerFindPrey.restart(); } @@ -115,113 +269,107 @@ public class MonsterAi extends EntityModule implements EntityMoveListener { private List getPathToPrey(Entity prey) { - return PathFinder.findPathRelative(entity.getPathfindingContext(), entity.getCoord(), prey.getCoord()); - } - - - protected double getScanRadius() - { - return sleeping ? 1 + rand.nextInt(3) : 4 + rand.nextInt(4); // For override - } - - - protected int getPreyAbandonDistance() - { - return 5 + rand.nextInt(4); // For override - } - - - @DefaultImpl - @Override - public void onStepFinished() - { - if (chasing) { - final Entity prey = entity.getLevel().getEntity(targetId); - if (prey == null || prey.isDead()) { - stopChasing(); - return; - } - - - stepTowardsPrey(prey); - - // TODO if close enough, attack. - } + if (!isPreyValid(prey)) return null; + + return entity.getPathFinder().findPathRelative(entity.getCoord(), prey.getCoord(), true); } private void stepTowardsPrey(Entity prey) { + //System.out.println("stepTowardsPrey"); + if (!isPreyValid(prey)) { + //System.out.println("prey dead?"); + return; + } + // if close enough - final Coord preyPos = prey.getCoord(); - if (preyPos.dist(entity.getCoord()) <= 1.5) { + if (isPreyInAttackRange(prey)) { + //System.out.println("attack"); attackPrey(prey); return; } final List preyPath = getPathToPrey(prey); - if (preyPath.size() > getPreyAbandonDistance()) { + if (preyPath == null || preyPath.size() > getPreyAbandonDistance()) { + //System.out.println("no path"); stopChasing(); return; } + //System.out.println("step to prey"); entity.pos.addStep(preyPath.get(0)); } private void attackPrey(Entity prey) { + if (!isPreyInAttackRange(prey)) { + //System.out.println("prey out of attack range, cant attack"); + return; + } + prey.receiveAttack(entity, getAttackStrength()); } - protected int getAttackStrength() + protected void setSleepTime(double secs) { - return 1; // For override + timerSleepStart.setDuration(secs); } - @Override - public void onPathFinished() + protected void setAttackTime(double secs) { + timerAttack.setDuration(secs); } - @Override - public void onPathInterrupted() + protected void setScanTime(double secs) { + timerFindPrey.setDuration(secs); } - @Override - public void save(IonBundle bundle) throws IOException + @DefaultImpl + protected double getScanRadius() { - bundle.putBundled("tscan", timerFindPrey); - bundle.putBundled("tsleep", timerSleepStart); + return sleeping ? 1 + rand.nextInt(3) : 4 + rand.nextInt(4); // For override } - @Override - public void load(IonBundle bundle) throws IOException + @DefaultImpl + protected int getPreyAbandonDistance() { - bundle.loadBundled("tscan", timerFindPrey); - bundle.loadBundled("tsleep", timerSleepStart); + return 5 + rand.nextInt(4); // For override } - @Override - public boolean isModuleSaved() + @DefaultImpl + protected double getAttackDistance() { - return true; + return 1.6; } - @Override - public void update(double delta) + @DefaultImpl + protected int getAttackStrength() { - timerFindPrey.update(delta); - timerSleepStart.update(delta); + return 1; // For override } + + @DefaultImpl + protected boolean shouldSkipScan() + { + return false; + } + + + @DefaultImpl + protected boolean shouldRandomlyAbandonPrey() + { + return false; + } } diff --git a/src/mightypork/rogue/world/entity/entities/PlayerEntity.java b/src/mightypork/rogue/world/entity/entities/PlayerEntity.java index de8c817..68b0b1f 100644 --- a/src/mightypork/rogue/world/entity/entities/PlayerEntity.java +++ b/src/mightypork/rogue/world/entity/entities/PlayerEntity.java @@ -2,7 +2,7 @@ package mightypork.rogue.world.entity.entities; import mightypork.gamecore.util.math.algo.Coord; -import mightypork.gamecore.util.math.algo.pathfinding.PathFindingContext; +import mightypork.gamecore.util.math.algo.pathfinding.PathFinder; import mightypork.rogue.world.entity.*; import mightypork.rogue.world.entity.modules.EntityMoveListener; import mightypork.rogue.world.entity.renderers.EntityRenderer; @@ -17,6 +17,8 @@ public class PlayerEntity extends Entity { public PlayerAi(Entity entity) { super(entity); + health.setMaxHealth(24); + health.fill(); } @@ -47,7 +49,7 @@ public class PlayerEntity extends Entity { } - private EntityPathfindingContext pathfc; + private PathFinder pathf; private EntityRenderer renderer; private final PlayerAi ai = new PlayerAi(this); @@ -65,24 +67,24 @@ public class PlayerEntity extends Entity { @Override - public PathFindingContext getPathfindingContext() + public PathFinder getPathFinder() { - if (pathfc == null) { - pathfc = new SimpleEntityPathFindingContext(this) { + if (pathf == null) { + pathf = new EntityPathFinder(this) { @Override public int getCost(Coord from, Coord to) - { - - if (!getLevel().getTile(pos.getCoord()).isExplored()) { return 1000; } - - return super.getCost(from, to); + { + if (!getLevel().getTile(pos.getCoord()).isExplored()) { + return 1000; + } + return super.getCost(from, to); }; }; } - return pathfc; + return pathf; } diff --git a/src/mightypork/rogue/world/entity/entities/RatAi.java b/src/mightypork/rogue/world/entity/entities/RatAi.java new file mode 100644 index 0000000..178fa92 --- /dev/null +++ b/src/mightypork/rogue/world/entity/entities/RatAi.java @@ -0,0 +1,59 @@ +package mightypork.rogue.world.entity.entities; + + +import mightypork.rogue.world.entity.Entity; + + +public class RatAi extends MonsterAi { + + public RatAi(Entity entity) + { + super(entity); + + setAttackTime(1); + setScanTime(2); + setSleepTime(100); + } + + + @Override + protected double getScanRadius() + { + return isSleeping() ? 2 + rand.nextInt(3) : 4 + rand.nextInt(3); + } + + + @Override + protected double getAttackDistance() + { + return 1.42; + } + + + @Override + protected int getAttackStrength() + { + return 1 + rand.nextInt(2); + } + + + @Override + protected int getPreyAbandonDistance() + { + return 8 + rand.nextInt(4); + } + + + @Override + protected boolean shouldSkipScan() + { + return false;//rand.nextInt(3) == 0; + } + + + @Override + protected boolean shouldRandomlyAbandonPrey() + { + return false;//rand.nextInt(8) == 0; + } +} diff --git a/src/mightypork/rogue/world/entity/entities/RatEntity.java b/src/mightypork/rogue/world/entity/entities/RatEntity.java new file mode 100644 index 0000000..8a4e050 --- /dev/null +++ b/src/mightypork/rogue/world/entity/entities/RatEntity.java @@ -0,0 +1,59 @@ +package mightypork.rogue.world.entity.entities; + + +import mightypork.gamecore.util.math.algo.pathfinding.PathFinder; +import mightypork.rogue.world.entity.*; +import mightypork.rogue.world.entity.renderers.EntityRenderer; +import mightypork.rogue.world.entity.renderers.EntityRendererMobLR; + + +public class RatEntity extends Entity { + + /** Navigation PFC */ + private PathFinder pathf; + + private final RatAi ai = new RatAi(this); + + private EntityRenderer renderer; + + + public RatEntity(EntityModel model, int eid) + { + super(model, eid); + + addModule("ai", ai); + pos.addMoveListener(ai); + + pos.setStepTime(0.5); + } + + + @Override + public PathFinder getPathFinder() + { + if (pathf == null) { + pathf = new EntityPathFinder(this); + } + + return pathf; + } + + + @Override + public EntityType getType() + { + return EntityType.MONSTER; + } + + + @Override + protected EntityRenderer getRenderer() + { + if (renderer == null) { + renderer = new EntityRendererMobLR(this, "sprite.player"); + } + + return renderer; + } + +} diff --git a/src/mightypork/rogue/world/entity/entities/SimpleMonster.java b/src/mightypork/rogue/world/entity/entities/SimpleMonster.java deleted file mode 100644 index 6e5af97..0000000 --- a/src/mightypork/rogue/world/entity/entities/SimpleMonster.java +++ /dev/null @@ -1,41 +0,0 @@ -package mightypork.rogue.world.entity.entities; - - -import mightypork.gamecore.util.math.algo.pathfinding.PathFindingContext; -import mightypork.rogue.world.entity.*; - - -public abstract class SimpleMonster extends Entity { - - /** Navigation PFC */ - private EntityPathfindingContext pathfc; - - private final EntityModule ai = new MonsterAi(this); - - - public SimpleMonster(EntityModel model, int eid) - { - super(model, eid); - - addModule("ai", ai); - } - - - @Override - public PathFindingContext getPathfindingContext() - { - if (pathfc == null) { - pathfc = new SimpleEntityPathFindingContext(this); - } - - return pathfc; - } - - - @Override - public EntityType getType() - { - return EntityType.MONSTER; - } - -} diff --git a/src/mightypork/rogue/world/entity/modules/EntityModuleHealth.java b/src/mightypork/rogue/world/entity/modules/EntityModuleHealth.java index 0fae315..d9ffc36 100644 --- a/src/mightypork/rogue/world/entity/modules/EntityModuleHealth.java +++ b/src/mightypork/rogue/world/entity/modules/EntityModuleHealth.java @@ -94,5 +94,11 @@ public class EntityModuleHealth extends EntityModule { { setHealth(health - attackStrength); } + + + public void fill() + { + setHealth(maxHealth); + } } diff --git a/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java b/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java index de801b6..f45272e 100644 --- a/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java +++ b/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java @@ -12,7 +12,6 @@ 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.pathfinding.PathFinder; -import mightypork.gamecore.util.math.algo.pathfinding.PathFindingContext; import mightypork.gamecore.util.math.constraints.vect.VectConst; import mightypork.rogue.world.entity.Entity; import mightypork.rogue.world.entity.EntityModule; @@ -67,7 +66,7 @@ public class EntityModulePosition extends EntityModule { } - public void setPosition(Coord coord) + public void setCoord(Coord coord) { entityPos.setTo(coord); lastPos.setTo(coord); @@ -87,7 +86,6 @@ public class EntityModulePosition extends EntityModule { if (walking && entityPos.isFinished()) { walking = false; - entity.getLevel().freeTile(lastPos); for (final EntityMoveListener l : moveListeners) { l.onStepFinished(); @@ -123,6 +121,7 @@ public class EntityModulePosition extends EntityModule { if (step.y() != 0) this.lastYDir = step.y(); lastPos.setTo(entityPos.getCoord()); + entity.getLevel().freeTile(lastPos);// entityPos.walk(step, stepTime); entity.getLevel().occupyTile(planned); } @@ -151,8 +150,7 @@ public class EntityModulePosition extends EntityModule { public boolean navigateTo(Coord target) { if (target.equals(getCoord())) return true; - final PathFindingContext pfc = entity.getPathfindingContext(); - final List newPath = PathFinder.findPathRelative(pfc, entityPos.getCoord(), target); + final List newPath = entity.getPathFinder().findPathRelative(entityPos.getCoord(), target); if (newPath == null) return false; cancelPath(); diff --git a/src/mightypork/rogue/world/entity/renderers/EntityRenderer.java b/src/mightypork/rogue/world/entity/renderers/EntityRenderer.java index 25d19ff..7dadbf7 100644 --- a/src/mightypork/rogue/world/entity/renderers/EntityRenderer.java +++ b/src/mightypork/rogue/world/entity/renderers/EntityRenderer.java @@ -5,16 +5,7 @@ import mightypork.rogue.world.entity.Entity; import mightypork.rogue.world.level.render.MapRenderContext; -public abstract class EntityRenderer { - - protected final Entity entity; - - - public EntityRenderer(Entity entity) - { - this.entity = entity; - } - +public abstract class EntityRenderer { public abstract void render(MapRenderContext context); diff --git a/src/mightypork/rogue/world/entity/renderers/EntityRendererMobLR.java b/src/mightypork/rogue/world/entity/renderers/EntityRendererMobLR.java index 316b253..329f061 100644 --- a/src/mightypork/rogue/world/entity/renderers/EntityRendererMobLR.java +++ b/src/mightypork/rogue/world/entity/renderers/EntityRendererMobLR.java @@ -22,11 +22,13 @@ public class EntityRendererMobLR extends EntityRenderer { private final TxSheet sheet; + protected final Entity entity; + public EntityRendererMobLR(Entity entity, String sheetKey) { - super(entity); - this.sheet = Res.getTxSheet(sheetKey); + this.entity = entity; + this.sheet = Res.sheet(sheetKey); } diff --git a/src/mightypork/rogue/world/gen/LevelGenerator.java b/src/mightypork/rogue/world/gen/LevelGenerator.java index 0c2761f..3f66132 100644 --- a/src/mightypork/rogue/world/gen/LevelGenerator.java +++ b/src/mightypork/rogue/world/gen/LevelGenerator.java @@ -4,6 +4,9 @@ package mightypork.rogue.world.gen; import java.util.Random; 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.DeadEndRoom; import mightypork.rogue.world.gen.rooms.Rooms; import mightypork.rogue.world.gen.themes.ThemeBrick; @@ -15,7 +18,7 @@ public class LevelGenerator { public static final MapTheme DUNGEON_THEME = new ThemeBrick(); - public static Level build(long seed, int complexity, MapTheme theme) + public static Level build(World world, long seed, int complexity, MapTheme theme) { final Random rand = new Random(seed + 13); @@ -39,6 +42,22 @@ public class LevelGenerator { map.writeToLevel(lvl); + // TODO tmp + // spawn rats + + Coord pos = Coord.make(0,0); + for(int i=0; i<1;i++) { // 4+complexity + rand.nextInt(1+complexity) + + Entity e = Entities.RAT.createEntity(world); + + for(int j=0; j<20;j++) { + pos.x = rand.nextInt(lvl.getWidth()); + pos.y = rand.nextInt(lvl.getHeight()); + + if(lvl.addEntity(e, pos)) break; + } + } + return lvl; } } diff --git a/src/mightypork/rogue/world/gen/ScratchMap.java b/src/mightypork/rogue/world/gen/ScratchMap.java index d5b016b..ea17080 100644 --- a/src/mightypork/rogue/world/gen/ScratchMap.java +++ b/src/mightypork/rogue/world/gen/ScratchMap.java @@ -14,7 +14,6 @@ import mightypork.gamecore.util.math.algo.Sides; import mightypork.gamecore.util.math.algo.Step; import mightypork.gamecore.util.math.algo.pathfinding.Heuristic; import mightypork.gamecore.util.math.algo.pathfinding.PathFinder; -import mightypork.gamecore.util.math.algo.pathfinding.PathFindingContext; import mightypork.rogue.world.level.Level; import mightypork.rogue.world.tile.Tile; import mightypork.rogue.world.tile.TileModel; @@ -37,7 +36,7 @@ public class ScratchMap { /** Coords to connect with corridors */ private final List nodes = new ArrayList<>(); - private final PathFindingContext pfc = new PathFindingContext() { + private final PathFinder pathf = new PathFinder() { @Override public boolean isAccessible(Coord pos) @@ -92,7 +91,7 @@ public class ScratchMap { @Override public Step[] getWalkSides() { - return Sides.cardinalSides; + return Sides.CARDINAL_SIDES; } }; @@ -291,7 +290,7 @@ public class ScratchMap { private void buildCorridor(Coord node1, Coord node2) { Log.f3("Building corridor " + node1 + " -> " + node2); - final List steps = PathFinder.findPath(pfc, node1, node2); + final List steps = pathf.findPath(node1, node2); if (steps == null) { Log.w("Could not build corridor " + node1 + "->" + node2); @@ -442,29 +441,29 @@ public class ScratchMap { break; } - if (isFloor && (nils & Sides.CARDINAL) != 0) { + if (isFloor && (nils & Sides.MASK_CARDINAL) != 0) { toWall = true; // floor with adjacent cardinal null break; } - if (isNull && (floors & Sides.DIAGONAL) != 0) { + if (isNull && (floors & Sides.MASK_DIAGONAL) != 0) { toWall = true; // null with adjacent diagonal floor break; } if (isDoor) { - if (countBits((byte) (floors & Sides.CARDINAL)) < 2) { + if (countBits((byte) (floors & Sides.MASK_CARDINAL)) < 2) { toWall = true; break; } - if (countBits((byte) (walls & Sides.CARDINAL)) > 2) { + if (countBits((byte) (walls & Sides.MASK_CARDINAL)) > 2) { toWall = true; break; } - if (countBits((byte) (floors & Sides.CARDINAL)) > 2) { + if (countBits((byte) (floors & Sides.MASK_CARDINAL)) > 2) { toFloor = true; break; } diff --git a/src/mightypork/rogue/world/gen/rooms/AbstractRectRoom.java b/src/mightypork/rogue/world/gen/rooms/AbstractRectRoom.java index 919ef68..af81b42 100644 --- a/src/mightypork/rogue/world/gen/rooms/AbstractRectRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/AbstractRectRoom.java @@ -72,7 +72,7 @@ public abstract class AbstractRectRoom implements RoomBuilder { break; } - if ((map.findDoors(door) & Sides.CARDINAL) == 0) { + if ((map.findDoors(door) & Sides.MASK_CARDINAL) == 0) { map.set(door, getDoorType(theme, rand)); i++; // increment pointer } diff --git a/src/mightypork/rogue/world/gui/MapView.java b/src/mightypork/rogue/world/gui/MapView.java index f20195b..c5216ad 100644 --- a/src/mightypork/rogue/world/gui/MapView.java +++ b/src/mightypork/rogue/world/gui/MapView.java @@ -43,7 +43,7 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL public MapView() { - this.tileSize = height().min(width()).div(8).max(32).mul(Num.make(1).sub(zoom.mul(0.66))); + this.tileSize = height().min(width()).div(12).max(32).mul(Num.make(1).sub(zoom.mul(0.66))); this.worldRenderer = new WorldRenderer(this, tileSize); pc = WorldProvider.get().getPlayerControl(); pc.addMoveListener(this); diff --git a/src/mightypork/rogue/world/level/Level.java b/src/mightypork/rogue/world/level/Level.java index 68d0a53..f7f74eb 100644 --- a/src/mightypork/rogue/world/level/Level.java +++ b/src/mightypork/rogue/world/level/Level.java @@ -173,7 +173,7 @@ public class Level implements MapAccess, IonObjBinary { // prepare entities for (final Entity ent : entitySet) { ent.setLevel(this); - occupyTile(ent.pos.getCoord()); + occupyTile(ent.getCoord()); entityMap.put(ent.getEntityId(), ent); } } @@ -241,6 +241,25 @@ public class Level implements MapAccess, IonObjBinary { } + /** + * Try to add entity at given pos + * @param entity the entity + * @param pos pos + * @return true if added (false if void, wall etc) + */ + public boolean addEntity(Entity entity, Coord pos) + { + Tile t = getTile(pos); + if (!t.isWalkable()) return false; + + addEntity(entity); + + entity.setCoord(pos); + + return true; + } + + public void addEntity(Entity entity) { if (entityMap.containsKey(entity.getEntityId())) { @@ -353,7 +372,7 @@ public class Level implements MapAccess, IonObjBinary { @Override public Step[] getSpreadSides() { - return Sides.allSides; + return Sides.ALL_SIDES; } diff --git a/src/mightypork/rogue/world/tile/Tile.java b/src/mightypork/rogue/world/tile/Tile.java index b1aab25..f811583 100644 --- a/src/mightypork/rogue/world/tile/Tile.java +++ b/src/mightypork/rogue/world/tile/Tile.java @@ -4,6 +4,7 @@ package mightypork.rogue.world.tile; import java.io.IOException; import java.util.Random; +import mightypork.gamecore.logging.Log; import mightypork.gamecore.util.annot.DefaultImpl; import mightypork.gamecore.util.ion.IonInput; import mightypork.gamecore.util.ion.IonObjBlob; @@ -22,14 +23,11 @@ import mightypork.rogue.world.level.render.TileRenderContext; public abstract class Tile implements IonObjBlob { // tmp extras - 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; // temporary flag for map. @@ -37,10 +35,9 @@ public abstract class Tile implements IonObjBlob { protected boolean explored; - public Tile(TileModel model, TileRenderer renderer) + public Tile(TileModel model) { this.model = model; - this.renderer = renderer; } @@ -52,14 +49,23 @@ public abstract class Tile implements IonObjBlob { { if (!isExplored()) return; - renderer.renderTile(context); + TileRenderer r = getRenderer(); + if (r == null) { + Log.e("Tile with no renderer: " + Log.str(this)); + return; + } + + r.renderTile(context); - if (doesReceiveShadow()) renderer.renderShadows(context); + if (doesReceiveShadow()) r.renderShadows(context); - renderer.renderUnexploredFog(context); + r.renderUnexploredFog(context); } + protected abstract TileRenderer getRenderer(); + + /** * Render extra stuff (ie. dropped items).
* Called after the whole map is rendered using renderTile. @@ -137,6 +143,7 @@ public abstract class Tile implements IonObjBlob { @DefaultImpl public void update(Level level, double delta) { + getRenderer().update(delta); } diff --git a/src/mightypork/rogue/world/tile/TileModel.java b/src/mightypork/rogue/world/tile/TileModel.java index 8abc344..a593914 100644 --- a/src/mightypork/rogue/world/tile/TileModel.java +++ b/src/mightypork/rogue/world/tile/TileModel.java @@ -16,15 +16,13 @@ public final class TileModel { /** Model ID */ public final int id; - public final TileRenderer renderer; public final Class tileClass; - public TileModel(int id, Class tile, TileRenderer renderer) + public TileModel(int id, Class tile) { Tiles.register(id, this); this.id = id; - this.renderer = renderer; this.tileClass = tile; } @@ -32,10 +30,10 @@ public final class TileModel { /** * @return new tile of this type */ - public Tile createTile() + public T createTile() { try { - return tileClass.getConstructor(TileModel.class, TileRenderer.class).newInstance(this, renderer); + return (T) tileClass.getConstructor(TileModel.class).newInstance(this); } catch (final Exception e) { throw new RuntimeException("Could not instantiate a tile.", e); } @@ -52,6 +50,8 @@ public final class TileModel { public void saveTile(IonOutput out, Tile tile) throws IOException { + if (tileClass != tile.getClass()) throw new RuntimeException("Tile class mismatch."); + tile.save(out); } } diff --git a/src/mightypork/rogue/world/tile/TileRenderData.java b/src/mightypork/rogue/world/tile/TileRenderData.java deleted file mode 100644 index 91fd829..0000000 --- a/src/mightypork/rogue/world/tile/TileRenderData.java +++ /dev/null @@ -1,14 +0,0 @@ -package mightypork.rogue.world.tile; - - -/** - * Data storage for tile renderer - * - * @author MightyPork - */ -public class TileRenderData { - - public byte shadows; - public boolean shadowsComputed; - -} diff --git a/src/mightypork/rogue/world/tile/TileRenderer.java b/src/mightypork/rogue/world/tile/TileRenderer.java index 904daa9..96c401a 100644 --- a/src/mightypork/rogue/world/tile/TileRenderer.java +++ b/src/mightypork/rogue/world/tile/TileRenderer.java @@ -1,30 +1,45 @@ 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.math.constraints.rect.Rect; import mightypork.rogue.Res; import mightypork.rogue.world.level.render.TileRenderContext; +import mightypork.rogue.world.tile.renderers.NullTileRenderer; /** - * Renderer for a tile model, in client + * Renderer for a tile; each tile has own renderer. * * @author MightyPork */ -public abstract class TileRenderer { +public abstract class TileRenderer implements Updateable { + + public static final TileRenderer NONE = new NullTileRenderer(); private static TxQuad SH_N, SH_S, SH_E, SH_W, SH_NW, SH_NE, SH_SW, SH_SE; private static TxQuad UFOG_N, UFOG_S, UFOG_E, UFOG_W, UFOG_NW, UFOG_NE, UFOG_SW, UFOG_SE; - - + private static boolean inited; + // data + + public byte shadows; + public boolean shadowsComputed; + + protected final Tile tile; + + protected Tile getTile() { + return tile; + } - public TileRenderer() + public TileRenderer(Tile tile) { + this.tile = tile; + if (!inited) { SH_N = Res.getTxQuad("tile.shadow.n"); SH_S = Res.getTxQuad("tile.shadow.s"); @@ -51,48 +66,44 @@ public abstract class TileRenderer { public void renderShadows(TileRenderContext context) - { - final TileRenderData trd = context.getTile().renderData; - - if (!trd.shadowsComputed) { + { + if (!shadowsComputed) { // no shadows computed yet - trd.shadows = 0; // reset the mask + shadows = 0; // reset the mask for (int i = 0; i < 8; i++) { final Tile t2 = context.getAdjacentTile(Sides.get(i)); if (!t2.isNull() && t2.doesCastShadow()) { - trd.shadows |= Sides.bit(i); + shadows |= Sides.bit(i); } } - trd.shadowsComputed = true; + shadowsComputed = true; } - if (trd.shadows == 0) return; + if (shadows == 0) return; final Rect rect = context.getRect(); - 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.NE_CORNER) == Sides.MASK_NE) Render.quadTextured(rect, SH_NE); + 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 ((trd.shadows & Sides.MASK_W) != 0) Render.quadTextured(rect, SH_W); - if ((trd.shadows & Sides.MASK_E) != 0) Render.quadTextured(rect, SH_E); + if ((shadows & Sides.MASK_W) != 0) Render.quadTextured(rect, SH_W); + if ((shadows & Sides.MASK_E) != 0) Render.quadTextured(rect, SH_E); - 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.SE_CORNER) == Sides.MASK_SE) Render.quadTextured(rect, SH_SE); + 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); } public void renderUnexploredFog(TileRenderContext context) { - // TODO cache in tile, update neighbouring tiles upon "explored" flag changed. + // TODO cache values, update neighbouring tiles upon "explored" flag changed. byte ufog = 0; - ufog = 0; // reset the mask - for (int i = 0; i < 8; i++) { final Tile t2 = context.getAdjacentTile(Sides.get(i)); if (t2.isNull() || !t2.isExplored()) { @@ -114,4 +125,9 @@ public abstract class TileRenderer { if ((ufog & Sides.MASK_S) != 0) Render.quadTextured(rect, UFOG_S); if ((ufog & Sides.SE_CORNER) == Sides.MASK_SE) Render.quadTextured(rect, UFOG_SE); } + + @Override + public void update(double delta) + { + } } diff --git a/src/mightypork/rogue/world/tile/Tiles.java b/src/mightypork/rogue/world/tile/Tiles.java index 041d2d8..cf06a2c 100644 --- a/src/mightypork/rogue/world/tile/Tiles.java +++ b/src/mightypork/rogue/world/tile/Tiles.java @@ -6,10 +6,14 @@ 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.DoorRenderer; -import mightypork.rogue.world.tile.renderers.LockedDoorRenderer; +import mightypork.rogue.world.tile.renderers.DoorTileRenderer; import mightypork.rogue.world.tile.renderers.NullTileRenderer; import mightypork.rogue.world.tile.tiles.*; +import mightypork.rogue.world.tile.tiles.brick.TileBrickDoor; +import mightypork.rogue.world.tile.tiles.brick.TileBrickFloor; +import mightypork.rogue.world.tile.tiles.brick.TileBrickPassage; +import mightypork.rogue.world.tile.tiles.brick.TileBrickSecretDoor; +import mightypork.rogue.world.tile.tiles.brick.TileBrickWall; /** @@ -21,13 +25,13 @@ public final class Tiles { private static final TileModel[] tiles = new TileModel[256]; - public static final TileModel NULL = new TileModel(0, NullTile.class, new NullTileRenderer()); + public static final TileModel NULL = new TileModel(0, NullTile.class); - 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 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 final TileModel BRICK_FLOOR = new TileModel(10, TileBrickFloor.class); + public static final TileModel BRICK_WALL = new TileModel(11, TileBrickWall.class); + public static final TileModel BRICK_DOOR = new TileModel(12, TileBrickDoor.class); + public static final TileModel BRICK_PASSAGE = new TileModel(13, TileBrickPassage.class); + public static final TileModel BRICK_HIDDEN_DOOR = new TileModel(14, TileBrickSecretDoor.class); public static void register(int id, TileModel model) diff --git a/src/mightypork/rogue/world/tile/renderers/BasicTileRenderer.java b/src/mightypork/rogue/world/tile/renderers/BasicTileRenderer.java index a3021f3..d7665da 100644 --- a/src/mightypork/rogue/world/tile/renderers/BasicTileRenderer.java +++ b/src/mightypork/rogue/world/tile/renderers/BasicTileRenderer.java @@ -4,8 +4,8 @@ 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; import mightypork.rogue.world.tile.TileRenderer; @@ -14,9 +14,10 @@ public class BasicTileRenderer extends TileRenderer { private final TxSheet sheet; - public BasicTileRenderer(String sheetKey) + public BasicTileRenderer(Tile tile, TxSheet sheet) { - this.sheet = Res.getTxSheet(sheetKey); + super(tile); + this.sheet = sheet; } diff --git a/src/mightypork/rogue/world/tile/renderers/DoorRenderer.java b/src/mightypork/rogue/world/tile/renderers/DoorRenderer.java deleted file mode 100644 index 9d3bbb1..0000000 --- a/src/mightypork/rogue/world/tile/renderers/DoorRenderer.java +++ /dev/null @@ -1,39 +0,0 @@ -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; -import mightypork.rogue.world.tile.TileRenderer; - - -public class DoorRenderer extends TileRenderer { - - private final TxSheet closed; - private final TxSheet open; - - - public DoorRenderer(String quadClosed, String quadOpen) - { - this.closed = Res.getTxSheet(quadClosed); - this.open = Res.getTxSheet(quadOpen); - } - - - @Override - public void renderTile(TileRenderContext context) - { - final Tile t = context.getTile(); - final Rect rect = context.getRect(); - - if (t.isOccupied()) { - Render.quadTextured(rect, open.getRandomQuad(context.getTileNoise())); - } else { - Render.quadTextured(rect, closed.getRandomQuad(context.getTileNoise())); - } - } - -} diff --git a/src/mightypork/rogue/world/tile/renderers/DoorTileRenderer.java b/src/mightypork/rogue/world/tile/renderers/DoorTileRenderer.java new file mode 100644 index 0000000..10ed24b --- /dev/null +++ b/src/mightypork/rogue/world/tile/renderers/DoorTileRenderer.java @@ -0,0 +1,70 @@ +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.gamecore.util.math.timing.TimedTask; +import mightypork.rogue.Res; +import mightypork.rogue.world.level.render.TileRenderContext; +import mightypork.rogue.world.tile.Tile; +import mightypork.rogue.world.tile.TileRenderer; +import mightypork.rogue.world.tile.tiles.TileBaseDoor; + + +public class DoorTileRenderer extends TileRenderer { + + private final TxSheet locked; + private final TxSheet closed; + private final TxSheet open; + + private boolean visuallyOpen = false; + + private final TimedTask closeTask = new TimedTask() { + + @Override + public void run() + { + System.out.println("CLOSEDOOR + "+ ((TileBaseDoor) tile).isOpen()); + visuallyOpen = ((TileBaseDoor) tile).isOpen(); + } + }; + + + public DoorTileRenderer(TileBaseDoor doorTile, TxSheet locked, TxSheet closed, TxSheet open) + { + super(doorTile); + + this.locked = locked; + this.closed = closed; + this.open = open; + } + + + @Override + public void renderTile(TileRenderContext context) + { + final Rect rect = context.getRect(); + + if (!visuallyOpen && ((TileBaseDoor) tile).isOpen()) visuallyOpen = true; + + if (visuallyOpen && !((TileBaseDoor) tile).isOpen()) { + if(!closeTask.isRunning()) closeTask.start(0.4); + } + + if (visuallyOpen) { + Render.quadTextured(rect, open.getRandomQuad(context.getTileNoise())); + } else { + TxSheet sheet = (((TileBaseDoor) tile).isLocked() ? locked : closed); + Render.quadTextured(rect, sheet.getRandomQuad(context.getTileNoise())); + } + } + + + @Override + public void update(double delta) + { + closeTask.update(delta); + } + +} diff --git a/src/mightypork/rogue/world/tile/renderers/LockedDoorRenderer.java b/src/mightypork/rogue/world/tile/renderers/LockedDoorRenderer.java deleted file mode 100644 index 053c2c8..0000000 --- a/src/mightypork/rogue/world/tile/renderers/LockedDoorRenderer.java +++ /dev/null @@ -1,38 +0,0 @@ -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; -import mightypork.rogue.world.tile.TileRenderer; - - -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/renderers/NullTileRenderer.java b/src/mightypork/rogue/world/tile/renderers/NullTileRenderer.java index e792c0c..f53ed4f 100644 --- a/src/mightypork/rogue/world/tile/renderers/NullTileRenderer.java +++ b/src/mightypork/rogue/world/tile/renderers/NullTileRenderer.java @@ -2,14 +2,44 @@ package mightypork.rogue.world.tile.renderers; import mightypork.rogue.world.level.render.TileRenderContext; +import mightypork.rogue.world.tile.Tile; import mightypork.rogue.world.tile.TileRenderer; +/** + * Do-nothing tile renderer + * + * @author MightyPork + */ public class NullTileRenderer extends TileRenderer { + public NullTileRenderer() + { + super(null); + } + + @Override public void renderTile(TileRenderContext context) { } + + @Override + public void renderShadows(TileRenderContext context) + { + } + + + @Override + public void renderUnexploredFog(TileRenderContext context) + { + } + + + @Override + public void update(double delta) + { + } + } diff --git a/src/mightypork/rogue/world/tile/tiles/DoorTile.java b/src/mightypork/rogue/world/tile/tiles/DoorTile.java deleted file mode 100644 index 5415ec4..0000000 --- a/src/mightypork/rogue/world/tile/tiles/DoorTile.java +++ /dev/null @@ -1,29 +0,0 @@ -package mightypork.rogue.world.tile.tiles; - - -import mightypork.rogue.world.tile.TileModel; -import mightypork.rogue.world.tile.TileRenderer; -import mightypork.rogue.world.tile.TileType; - - -public class DoorTile extends SolidTile { - - public DoorTile(TileModel model, TileRenderer renderer) - { - super(model, renderer); - } - - - @Override - public boolean isWalkable() - { - return true; - } - - - @Override - public TileType getType() - { - return TileType.DOOR; - } -} diff --git a/src/mightypork/rogue/world/tile/tiles/FloorTile.java b/src/mightypork/rogue/world/tile/tiles/FloorTile.java deleted file mode 100644 index af8e57b..0000000 --- a/src/mightypork/rogue/world/tile/tiles/FloorTile.java +++ /dev/null @@ -1,22 +0,0 @@ -package mightypork.rogue.world.tile.tiles; - - -import mightypork.rogue.world.tile.TileModel; -import mightypork.rogue.world.tile.TileRenderer; -import mightypork.rogue.world.tile.TileType; - - -public class FloorTile extends GroundTile { - - public FloorTile(TileModel model, TileRenderer renderer) - { - super(model, renderer); - } - - - @Override - public TileType getType() - { - return TileType.FLOOR; - } -} diff --git a/src/mightypork/rogue/world/tile/tiles/LockedDoorTile.java b/src/mightypork/rogue/world/tile/tiles/LockedDoorTile.java deleted file mode 100644 index 5e34df1..0000000 --- a/src/mightypork/rogue/world/tile/tiles/LockedDoorTile.java +++ /dev/null @@ -1,44 +0,0 @@ -package mightypork.rogue.world.tile.tiles; - - -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.TileRenderer; - - -public class LockedDoorTile extends DoorTile { - - public boolean locked = true; - - - public LockedDoorTile(TileModel model, TileRenderer renderer) - { - super(model, renderer); - } - - - @Override - public boolean isWalkable() - { - return !locked; - } - - - @Override - public void load(IonInput in) throws IOException - { - super.load(in); - locked = in.readBoolean(); - } - - - @Override - public void save(IonOutput out) throws IOException - { - super.save(out); - out.writeBoolean(locked); - } -} diff --git a/src/mightypork/rogue/world/tile/tiles/NullTile.java b/src/mightypork/rogue/world/tile/tiles/NullTile.java index 10c2b58..e1d5678 100644 --- a/src/mightypork/rogue/world/tile/tiles/NullTile.java +++ b/src/mightypork/rogue/world/tile/tiles/NullTile.java @@ -12,9 +12,15 @@ import mightypork.rogue.world.tile.TileType; public class NullTile extends Tile { - public NullTile(TileModel model, TileRenderer renderer) + public NullTile(TileModel model) { - super(model, renderer); + super(model); + } + + @Override + protected TileRenderer getRenderer() + { + return TileRenderer.NONE; } diff --git a/src/mightypork/rogue/world/tile/tiles/TileBaseDoor.java b/src/mightypork/rogue/world/tile/tiles/TileBaseDoor.java new file mode 100644 index 0000000..9fa4d29 --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/TileBaseDoor.java @@ -0,0 +1,82 @@ +package mightypork.rogue.world.tile.tiles; + + +import java.io.IOException; + +import mightypork.gamecore.resources.textures.TxSheet; +import mightypork.gamecore.util.ion.IonInput; +import mightypork.gamecore.util.ion.IonOutput; +import mightypork.rogue.world.tile.TileModel; +import mightypork.rogue.world.tile.TileRenderer; +import mightypork.rogue.world.tile.TileType; +import mightypork.rogue.world.tile.renderers.DoorTileRenderer; + + +public abstract class TileBaseDoor extends TileSolid { + + private final DoorTileRenderer renderer; + protected boolean locked = false; + + + public TileBaseDoor(TileModel model, TxSheet locked, TxSheet closed, TxSheet open) + { + super(model); + + this.renderer = new DoorTileRenderer(this, locked, closed, open); + } + + + @Override + protected TileRenderer getRenderer() + { + return renderer; + } + + + @Override + public boolean isWalkable() + { + return !locked; + } + + + @Override + public TileType getType() + { + return TileType.DOOR; + } + + + @Override + public void load(IonInput in) throws IOException + { + super.load(in); + locked = in.readBoolean(); + } + + + @Override + public void save(IonOutput out) throws IOException + { + super.save(out); + out.writeBoolean(locked); + } + + + /** + * @return true if the door appears open + */ + public boolean isOpen() + { + return isOccupied(); + } + + + /** + * @return true if the door is locked + */ + public boolean isLocked() + { + return locked; + } +} diff --git a/src/mightypork/rogue/world/tile/tiles/TileBaseFloor.java b/src/mightypork/rogue/world/tile/tiles/TileBaseFloor.java new file mode 100644 index 0000000..73b7dfa --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/TileBaseFloor.java @@ -0,0 +1,34 @@ +package mightypork.rogue.world.tile.tiles; + + +import mightypork.gamecore.resources.textures.TxSheet; +import mightypork.rogue.world.tile.TileModel; +import mightypork.rogue.world.tile.TileRenderer; +import mightypork.rogue.world.tile.TileType; +import mightypork.rogue.world.tile.renderers.BasicTileRenderer; + + +public abstract class TileBaseFloor extends TileWalkable { + + private BasicTileRenderer renderer; + + + public TileBaseFloor(TileModel model, TxSheet sheet) + { + super(model); + this.renderer = new BasicTileRenderer(this, sheet); + } + + @Override + protected TileRenderer getRenderer() + { + return renderer; + } + + + @Override + public TileType getType() + { + return TileType.FLOOR; + } +} diff --git a/src/mightypork/rogue/world/tile/tiles/TileBasePassage.java b/src/mightypork/rogue/world/tile/tiles/TileBasePassage.java new file mode 100644 index 0000000..260df13 --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/TileBasePassage.java @@ -0,0 +1,49 @@ +package mightypork.rogue.world.tile.tiles; + + +import mightypork.gamecore.resources.textures.TxSheet; +import mightypork.rogue.world.tile.TileModel; +import mightypork.rogue.world.tile.TileRenderer; +import mightypork.rogue.world.tile.TileType; +import mightypork.rogue.world.tile.renderers.BasicTileRenderer; + + +/** + * Collapsed wall that's walk-through + * + * @author MightyPork + */ +public abstract class TileBasePassage extends TileSolid { + + private BasicTileRenderer renderer; + + + public TileBasePassage(TileModel model, TxSheet sheet) + { + super(model); + + this.renderer = new BasicTileRenderer(this, sheet); + } + + + @Override + protected TileRenderer getRenderer() + { + return renderer; + } + + + @Override + public TileType getType() + { + return TileType.PASSAGE; + } + + + @Override + public boolean isWalkable() + { + return true; + } + +} diff --git a/src/mightypork/rogue/world/tile/tiles/SecretDoorTile.java b/src/mightypork/rogue/world/tile/tiles/TileBaseSecretDoor.java similarity index 72% rename from src/mightypork/rogue/world/tile/tiles/SecretDoorTile.java rename to src/mightypork/rogue/world/tile/tiles/TileBaseSecretDoor.java index b46b795..ac27242 100644 --- a/src/mightypork/rogue/world/tile/tiles/SecretDoorTile.java +++ b/src/mightypork/rogue/world/tile/tiles/TileBaseSecretDoor.java @@ -3,24 +3,27 @@ package mightypork.rogue.world.tile.tiles; 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.color.Color; +import mightypork.gamecore.util.math.color.pal.RGB; import mightypork.gamecore.util.math.timing.TimedTask; import mightypork.rogue.world.level.Level; import mightypork.rogue.world.tile.TileModel; import mightypork.rogue.world.tile.TileRenderer; import mightypork.rogue.world.tile.TileType; +import mightypork.rogue.world.tile.renderers.DoorTileRenderer; -public class SecretDoorTile extends LockedDoorTile { +public abstract class TileBaseSecretDoor extends TileBaseDoor { private int clicks = 2 + rand.nextInt(2); - public SecretDoorTile(TileModel model, TileRenderer renderer) + public TileBaseSecretDoor(TileModel model, TxSheet secret, TxSheet closed, TxSheet open) { - super(model, renderer); + super(model, secret, closed, open); } @@ -41,7 +44,7 @@ public class SecretDoorTile extends LockedDoorTile { public Color getMapColor() { if (locked) return TileType.WALL.getMapColor(); - return super.getMapColor(); + return RGB.PINK; } diff --git a/src/mightypork/rogue/world/tile/tiles/TileBaseWall.java b/src/mightypork/rogue/world/tile/tiles/TileBaseWall.java new file mode 100644 index 0000000..78a9894 --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/TileBaseWall.java @@ -0,0 +1,35 @@ +package mightypork.rogue.world.tile.tiles; + + +import mightypork.gamecore.resources.textures.TxSheet; +import mightypork.rogue.world.level.render.TileRenderContext; +import mightypork.rogue.world.tile.TileModel; +import mightypork.rogue.world.tile.TileRenderer; +import mightypork.rogue.world.tile.TileType; +import mightypork.rogue.world.tile.renderers.BasicTileRenderer; + + +public abstract class TileBaseWall extends TileSolid { + + private BasicTileRenderer renderer; + + + public TileBaseWall(TileModel model, TxSheet sheet) + { + super(model); + this.renderer = new BasicTileRenderer(this, sheet); + } + + + public BasicTileRenderer getRenderer() + { + return renderer; + } + + + @Override + public TileType getType() + { + return TileType.WALL; + } +} diff --git a/src/mightypork/rogue/world/tile/tiles/SolidTile.java b/src/mightypork/rogue/world/tile/tiles/TileSolid.java similarity index 81% rename from src/mightypork/rogue/world/tile/tiles/SolidTile.java rename to src/mightypork/rogue/world/tile/tiles/TileSolid.java index d88ce7b..7c18047 100644 --- a/src/mightypork/rogue/world/tile/tiles/SolidTile.java +++ b/src/mightypork/rogue/world/tile/tiles/TileSolid.java @@ -7,11 +7,11 @@ import mightypork.rogue.world.tile.TileModel; import mightypork.rogue.world.tile.TileRenderer; -public abstract class SolidTile extends Tile { +public abstract class TileSolid extends Tile { - public SolidTile(TileModel model, TileRenderer renderer) + public TileSolid(TileModel model) { - super(model, renderer); + super(model); } diff --git a/src/mightypork/rogue/world/tile/tiles/GroundTile.java b/src/mightypork/rogue/world/tile/tiles/TileWalkable.java similarity index 92% rename from src/mightypork/rogue/world/tile/tiles/GroundTile.java rename to src/mightypork/rogue/world/tile/tiles/TileWalkable.java index 678c45b..4488b35 100644 --- a/src/mightypork/rogue/world/tile/tiles/GroundTile.java +++ b/src/mightypork/rogue/world/tile/tiles/TileWalkable.java @@ -15,16 +15,16 @@ import mightypork.rogue.world.tile.TileModel; import mightypork.rogue.world.tile.TileRenderer; -public abstract class GroundTile extends Tile { +public abstract class TileWalkable extends Tile { private final DroppedItemRenderer itemRenderer = new DroppedItemRenderer(); protected final Stack items = new Stack<>(); - public GroundTile(TileModel model, TileRenderer renderer) + public TileWalkable(TileModel model) { - super(model, renderer); + super(model); } @@ -40,6 +40,7 @@ public abstract class GroundTile extends Tile { @Override public void update(Level level, double delta) { + super.update(level, delta); itemRenderer.update(delta); } diff --git a/src/mightypork/rogue/world/tile/tiles/WallPassageTile.java b/src/mightypork/rogue/world/tile/tiles/WallPassageTile.java deleted file mode 100644 index 0af638d..0000000 --- a/src/mightypork/rogue/world/tile/tiles/WallPassageTile.java +++ /dev/null @@ -1,35 +0,0 @@ -package mightypork.rogue.world.tile.tiles; - - -import mightypork.rogue.world.tile.TileModel; -import mightypork.rogue.world.tile.TileRenderer; -import mightypork.rogue.world.tile.TileType; - - -/** - * Collapsed wall that's walk-through - * - * @author MightyPork - */ -public class WallPassageTile extends SolidTile { - - public WallPassageTile(TileModel model, TileRenderer renderer) - { - super(model, renderer); - } - - - @Override - public TileType getType() - { - return TileType.PASSAGE; - } - - - @Override - public boolean isWalkable() - { - return true; - } - -} diff --git a/src/mightypork/rogue/world/tile/tiles/WallTile.java b/src/mightypork/rogue/world/tile/tiles/WallTile.java deleted file mode 100644 index e023322..0000000 --- a/src/mightypork/rogue/world/tile/tiles/WallTile.java +++ /dev/null @@ -1,22 +0,0 @@ -package mightypork.rogue.world.tile.tiles; - - -import mightypork.rogue.world.tile.TileModel; -import mightypork.rogue.world.tile.TileRenderer; -import mightypork.rogue.world.tile.TileType; - - -public class WallTile extends SolidTile { - - public WallTile(TileModel model, TileRenderer renderer) - { - super(model, renderer); - } - - - @Override - public TileType getType() - { - return TileType.WALL; - } -} diff --git a/src/mightypork/rogue/world/tile/tiles/brick/TileBrickDoor.java b/src/mightypork/rogue/world/tile/tiles/brick/TileBrickDoor.java new file mode 100644 index 0000000..0ed365c --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/brick/TileBrickDoor.java @@ -0,0 +1,22 @@ +package mightypork.rogue.world.tile.tiles.brick; + +import mightypork.rogue.Res; +import mightypork.rogue.world.tile.TileModel; +import mightypork.rogue.world.tile.tiles.TileBaseDoor; + + +public class TileBrickDoor extends TileBaseDoor { + + public TileBrickDoor(TileModel model) + { + //@formatter:off + super( + model, + Res.sheet("tile.brick.door.locked"), + Res.sheet("tile.brick.door.closed"), + Res.sheet("tile.brick.door.open") + ); + //@formatter:on + } + +} diff --git a/src/mightypork/rogue/world/tile/tiles/brick/TileBrickFloor.java b/src/mightypork/rogue/world/tile/tiles/brick/TileBrickFloor.java new file mode 100644 index 0000000..ac42a19 --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/brick/TileBrickFloor.java @@ -0,0 +1,16 @@ +package mightypork.rogue.world.tile.tiles.brick; + +import mightypork.gamecore.resources.textures.TxSheet; +import mightypork.rogue.Res; +import mightypork.rogue.world.tile.TileModel; +import mightypork.rogue.world.tile.tiles.TileBaseFloor; + + +public class TileBrickFloor extends TileBaseFloor { + + public TileBrickFloor(TileModel model) + { + super(model, Res.sheet("tile.brick.floor")); + } + +} diff --git a/src/mightypork/rogue/world/tile/tiles/brick/TileBrickPassage.java b/src/mightypork/rogue/world/tile/tiles/brick/TileBrickPassage.java new file mode 100644 index 0000000..f7949c5 --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/brick/TileBrickPassage.java @@ -0,0 +1,17 @@ +package mightypork.rogue.world.tile.tiles.brick; + + +import mightypork.rogue.Res; +import mightypork.rogue.world.tile.TileModel; +import mightypork.rogue.world.tile.tiles.TileBaseDoor; +import mightypork.rogue.world.tile.tiles.TileBasePassage; + + +public class TileBrickPassage extends TileBasePassage { + + public TileBrickPassage(TileModel model) + { + super(model, Res.sheet("tile.brick.passage")); + } + +} diff --git a/src/mightypork/rogue/world/tile/tiles/brick/TileBrickSecretDoor.java b/src/mightypork/rogue/world/tile/tiles/brick/TileBrickSecretDoor.java new file mode 100644 index 0000000..7e33524 --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/brick/TileBrickSecretDoor.java @@ -0,0 +1,26 @@ +package mightypork.rogue.world.tile.tiles.brick; + +import mightypork.gamecore.util.math.color.Color; +import mightypork.gamecore.util.math.color.pal.RGB; +import mightypork.rogue.Res; +import mightypork.rogue.world.tile.TileModel; +import mightypork.rogue.world.tile.tiles.TileBaseDoor; +import mightypork.rogue.world.tile.tiles.TileBaseSecretDoor; + + +public class TileBrickSecretDoor extends TileBaseSecretDoor { + + public TileBrickSecretDoor(TileModel model) + { + //@formatter:off + super( + model, + Res.sheet("tile.brick.door.secret"), + Res.sheet("tile.brick.door.closed"), + Res.sheet("tile.brick.door.open") + ); + //@formatter:on + + locked = true; // hide it + } +} diff --git a/src/mightypork/rogue/world/tile/tiles/brick/TileBrickWall.java b/src/mightypork/rogue/world/tile/tiles/brick/TileBrickWall.java new file mode 100644 index 0000000..d8b9ee5 --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/brick/TileBrickWall.java @@ -0,0 +1,16 @@ +package mightypork.rogue.world.tile.tiles.brick; + +import mightypork.gamecore.resources.textures.TxSheet; +import mightypork.rogue.Res; +import mightypork.rogue.world.tile.TileModel; +import mightypork.rogue.world.tile.tiles.TileBaseWall; + + +public class TileBrickWall extends TileBaseWall { + + public TileBrickWall(TileModel model) + { + super(model, Res.sheet("tile.brick.wall")); + } + +}