From d8deaecb00dd3ffcf70c49bb2a76d877f5aac5fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Mon, 28 Apr 2014 10:33:18 +0200 Subject: [PATCH] rewritten tile system, added intial flood fil system --- src/mightypork/rogue/App.java | 2 - .../screens/gamescreen/world/Minimap.java | 2 +- .../world/entity/models/PlayerModel.java | 2 +- .../rogue/world/gen/ScratchMap.java | 40 +++-- src/mightypork/rogue/world/level/Level.java | 12 +- .../world/level/render/TileRenderContext.java | 4 +- .../rogue/world/pathfinding/FillContext.java | 21 +++ .../rogue/world/pathfinding/FloodFill.java | 41 +++++ src/mightypork/rogue/world/tile/Tile.java | 169 +++++------------- src/mightypork/rogue/world/tile/TileData.java | 54 ------ .../rogue/world/tile/TileModel.java | 76 +++----- .../rogue/world/tile/TileRenderer.java | 58 +----- src/mightypork/rogue/world/tile/TileType.java | 12 ++ src/mightypork/rogue/world/tile/Tiles.java | 65 ++++--- .../world/tile/models/AbstractNullTile.java | 53 ------ .../rogue/world/tile/models/AbstractTile.java | 62 ------- .../rogue/world/tile/models/Floor.java | 50 ------ .../rogue/world/tile/models/NullTile.java | 29 --- .../rogue/world/tile/models/SimpleDoor.java | 65 ------- .../rogue/world/tile/models/Wall.java | 55 ------ ...oorRenderer.java => DoorTileRenderer.java} | 4 +- .../tile/renderers/NullTileRenderer.java | 2 +- .../rogue/world/tile/tiles/BasicTile.java | 58 ++++++ .../rogue/world/tile/tiles/DoorTile.java | 46 +++++ .../rogue/world/tile/tiles/FloorTile.java | 45 +++++ .../world/tile/tiles/LockedDoorTile.java | 36 ++++ .../rogue/world/tile/tiles/NullTile.java | 86 +++++++++ .../rogue/world/tile/tiles/TileWithItems.java | 64 +++++++ .../rogue/world/tile/tiles/WallTile.java | 46 +++++ src/mightypork/util/files/ion/IonBinary.java | 23 +-- .../util/files/ion/IonBinaryHeadless.java | 31 ++++ 31 files changed, 634 insertions(+), 679 deletions(-) create mode 100644 src/mightypork/rogue/world/pathfinding/FillContext.java create mode 100644 src/mightypork/rogue/world/pathfinding/FloodFill.java delete mode 100644 src/mightypork/rogue/world/tile/TileData.java create mode 100644 src/mightypork/rogue/world/tile/TileType.java delete mode 100644 src/mightypork/rogue/world/tile/models/AbstractNullTile.java delete mode 100644 src/mightypork/rogue/world/tile/models/AbstractTile.java delete mode 100644 src/mightypork/rogue/world/tile/models/Floor.java delete mode 100644 src/mightypork/rogue/world/tile/models/NullTile.java delete mode 100644 src/mightypork/rogue/world/tile/models/SimpleDoor.java delete mode 100644 src/mightypork/rogue/world/tile/models/Wall.java rename src/mightypork/rogue/world/tile/renderers/{DoorRenderer.java => DoorTileRenderer.java} (87%) create mode 100644 src/mightypork/rogue/world/tile/tiles/BasicTile.java create mode 100644 src/mightypork/rogue/world/tile/tiles/DoorTile.java create mode 100644 src/mightypork/rogue/world/tile/tiles/FloorTile.java create mode 100644 src/mightypork/rogue/world/tile/tiles/LockedDoorTile.java create mode 100644 src/mightypork/rogue/world/tile/tiles/NullTile.java create mode 100644 src/mightypork/rogue/world/tile/tiles/TileWithItems.java create mode 100644 src/mightypork/rogue/world/tile/tiles/WallTile.java create mode 100644 src/mightypork/util/files/ion/IonBinaryHeadless.java diff --git a/src/mightypork/rogue/App.java b/src/mightypork/rogue/App.java index c0050a3..05d778a 100644 --- a/src/mightypork/rogue/App.java +++ b/src/mightypork/rogue/App.java @@ -25,7 +25,6 @@ import mightypork.rogue.screens.test_render.ScreenTestRender; import mightypork.rogue.world.entity.Entity; import mightypork.rogue.world.item.Item; import mightypork.rogue.world.level.Level; -import mightypork.rogue.world.tile.Tile; import mightypork.util.control.eventbus.BusEvent; import mightypork.util.control.eventbus.EventBus; import mightypork.util.files.ion.Ion; @@ -107,7 +106,6 @@ public final class App extends BaseApp { @Override protected void preInit() { - Ion.registerBinary(Tile.ION_MARK, Tile.class); Ion.registerBinary(Item.ION_MARK, Item.class); Ion.registerBinary(Level.ION_MARK, Level.class); Ion.registerBinary(Entity.ION_MARK, Entity.class); diff --git a/src/mightypork/rogue/screens/gamescreen/world/Minimap.java b/src/mightypork/rogue/screens/gamescreen/world/Minimap.java index 3d744e3..0211c07 100644 --- a/src/mightypork/rogue/screens/gamescreen/world/Minimap.java +++ b/src/mightypork/rogue/screens/gamescreen/world/Minimap.java @@ -64,7 +64,7 @@ public class Minimap extends InputComponent implements MouseButtonListener { for (pos.x = 0, point.x = tl.xi(); pos.x < lw; pos.x++, point.x += unit) { final Tile t = lvl.getTile(pos); - if (t.isNull() || !t.data.explored) continue; + if (t.isNull() || !t.isExplored()) continue; final Color clr = t.getMapColor(); diff --git a/src/mightypork/rogue/world/entity/models/PlayerModel.java b/src/mightypork/rogue/world/entity/models/PlayerModel.java index 663ea79..9c910ff 100644 --- a/src/mightypork/rogue/world/entity/models/PlayerModel.java +++ b/src/mightypork/rogue/world/entity/models/PlayerModel.java @@ -86,7 +86,7 @@ public class PlayerModel extends EntityModel { @Override public int getPathCost(Entity entity, Coord from, Coord to) { - if (!entity.getLevel().getTile(entity.getCoord()).data.explored) { + if (!entity.getLevel().getTile(entity.getCoord()).isExplored()) { return 1000; } diff --git a/src/mightypork/rogue/world/gen/ScratchMap.java b/src/mightypork/rogue/world/gen/ScratchMap.java index e7233a2..bc3803f 100644 --- a/src/mightypork/rogue/world/gen/ScratchMap.java +++ b/src/mightypork/rogue/world/gen/ScratchMap.java @@ -15,6 +15,7 @@ import mightypork.rogue.world.pathfinding.PathFinder; import mightypork.rogue.world.pathfinding.PathFindingContext; import mightypork.rogue.world.tile.Tile; import mightypork.rogue.world.tile.TileModel; +import mightypork.rogue.world.tile.TileType; import mightypork.rogue.world.tile.Tiles; import mightypork.util.logging.Log; import mightypork.util.math.Calc; @@ -43,14 +44,24 @@ public class ScratchMap { { final Tile t = get(pos); - if (t.isNull()) return 60; - - if (t.isDoor()) return 10; // door - if (t.isFloor()) return 20; // floor - - if (t.isWall() && t.genData.isProtected) return 1000; - - return 100; // wall + switch (t.getType()) { + case NULL: + return 60; + + case DOOR: + return 10; + + case FLOOR: + return 20; + + case WALL: + if (t.genData.isProtected) return 1000; + + return 100; + + default: + throw new RuntimeException("Unknown tile type: " + t.getType()); + } } @@ -79,7 +90,8 @@ public class ScratchMap { private static final boolean FIX_GLITCHES = true; - public ScratchMap(int max_size, Theme theme, Random rand) { + public ScratchMap(int max_size, Theme theme, Random rand) + { map = new Tile[max_size][max_size]; genMin = Coord.make((max_size / 2) - 1, (max_size / 2) - 1); @@ -161,9 +173,7 @@ public class ScratchMap { public Tile get(Coord pos) { - if (!isIn(pos)) { - throw new IndexOutOfBoundsException("Tile not in map: " + pos); - } + if (!isIn(pos)) { throw new IndexOutOfBoundsException("Tile not in map: " + pos); } return map[pos.y][pos.x]; } @@ -177,9 +187,7 @@ public class ScratchMap { public boolean set(Coord pos, Tile tile) { - if (!isIn(pos)) { - throw new IndexOutOfBoundsException("Tile not in map: " + pos); - } + if (!isIn(pos)) { throw new IndexOutOfBoundsException("Tile not in map: " + pos); } map[pos.y][pos.x] = tile; return true; @@ -295,7 +303,7 @@ public class ScratchMap { final Tile current = get(c); if (!current.isNull() && (current.isPotentiallyWalkable())) continue; // floor already, let it be - + if (i == 0 && j == 0) { set(c, theme.floor()); } else { diff --git a/src/mightypork/rogue/world/level/Level.java b/src/mightypork/rogue/world/level/Level.java index 7c770da..671ad8c 100644 --- a/src/mightypork/rogue/world/level/Level.java +++ b/src/mightypork/rogue/world/level/Level.java @@ -100,7 +100,7 @@ public class Level implements MapAccess, IonBinary { public final void setTile(Coord pos, int tileId) { - setTile(pos, new Tile(tileId)); + setTile(pos, Tiles.create(tileId)); } @@ -163,10 +163,7 @@ public class Level implements MapAccess, IonBinary { // load tiles for (final Coord c = Coord.zero(); c.x < size.x; c.x++) { for (c.y = 0; c.y < size.y; c.y++) { - // no mark - final Tile tile = new Tile(); - tile.load(in); - setTile(c, tile); + setTile(c, Tiles.loadTile(in)); } } @@ -192,8 +189,7 @@ public class Level implements MapAccess, IonBinary { for (final Coord c = Coord.zero(); c.x < size.x; c.x++) { for (c.y = 0; c.y < size.y; c.y++) { - // no mark to save space - getTile(c).save(out); + Tiles.saveTile(out, getTile(c)); } } } @@ -333,7 +329,7 @@ public class Level implements MapAccess, IonBinary { if (Calc.dist(coord.x, coord.y, c.x, c.y) > radius) continue; final Tile t = getTile(c); if (!t.isNull()) { - t.data.explored = true; + t.setExplored(); } } } diff --git a/src/mightypork/rogue/world/level/render/TileRenderContext.java b/src/mightypork/rogue/world/level/render/TileRenderContext.java index 7cdbe1c..43ecb60 100644 --- a/src/mightypork/rogue/world/level/render/TileRenderContext.java +++ b/src/mightypork/rogue/world/level/render/TileRenderContext.java @@ -24,7 +24,7 @@ public final class TileRenderContext extends MapRenderContext implements RectBou { super(map, drawArea); - this.tiler.setOverlap(0.01); // avoid gaps (rounding error?) + //this.tiler.setOverlap(0.02); // avoid gaps (rounding error?) this.noise = map.getNoiseGen(); } @@ -69,7 +69,7 @@ public final class TileRenderContext extends MapRenderContext implements RectBou public void renderItems() { - map.getTile(pos).renderItems(this); + map.getTile(pos).renderExtra(this); } diff --git a/src/mightypork/rogue/world/pathfinding/FillContext.java b/src/mightypork/rogue/world/pathfinding/FillContext.java new file mode 100644 index 0000000..10c3cb8 --- /dev/null +++ b/src/mightypork/rogue/world/pathfinding/FillContext.java @@ -0,0 +1,21 @@ +package mightypork.rogue.world.pathfinding; + + +import mightypork.rogue.world.Coord; + + +public interface FillContext { + + boolean canEnter(Coord pos); + + + boolean canSpread(Coord pos); + + + /** + * Get the max distance filled form start point. Use -1 for unlimited range. + * + * @return max distance + */ + int getMaxDistance(); +} diff --git a/src/mightypork/rogue/world/pathfinding/FloodFill.java b/src/mightypork/rogue/world/pathfinding/FloodFill.java new file mode 100644 index 0000000..6decd8d --- /dev/null +++ b/src/mightypork/rogue/world/pathfinding/FloodFill.java @@ -0,0 +1,41 @@ +package mightypork.rogue.world.pathfinding; + + +import java.util.*; + +import mightypork.rogue.world.Coord; + + +public class FloodFill { + + private static final Coord[] spread = { Coord.make(0, -1), Coord.make(0, 1), Coord.make(1, 0), Coord.make(-1, 0) }; + + + public static final Collection fill(Coord start, FillContext context) + { + Set filled = new HashSet<>(); + Stack active = new Stack<>(); + + int maxDist = context.getMaxDistance(); + + active.push(start); + + while (!active.isEmpty()) { + Coord current = active.pop(); + + filled.add(current); + + for (Coord spr : spread) { + Coord next = current.add(spr); + + if (next.dist(start) > maxDist) continue; + + if (context.canSpread(next)) { + active.push(next); + } + } + } + + return filled; + } +} diff --git a/src/mightypork/rogue/world/tile/Tile.java b/src/mightypork/rogue/world/tile/Tile.java index b7b495c..719caf8 100644 --- a/src/mightypork/rogue/world/tile/Tile.java +++ b/src/mightypork/rogue/world/tile/Tile.java @@ -8,6 +8,7 @@ import mightypork.rogue.world.item.Item; import mightypork.rogue.world.level.Level; import mightypork.rogue.world.level.render.TileRenderContext; import mightypork.util.files.ion.IonBinary; +import mightypork.util.files.ion.IonBinaryHeadless; import mightypork.util.files.ion.IonInput; import mightypork.util.files.ion.IonOutput; import mightypork.util.math.color.Color; @@ -18,211 +19,129 @@ import mightypork.util.math.color.Color; * * @author MightyPork */ -public final class Tile implements IonBinary { - - public static final short ION_MARK = 50; - - private TileModel model; - private TileRenderer renderer; - - private int id; - - private final Stack items = new Stack<>(); - - /** persistent field for model, reflected by renderer */ - public final TileData data = new TileData(); +public abstract class Tile implements IonBinaryHeadless { + // tmp extras public final TileRenderData renderData = new TileRenderData(); public final TileGenData genData = new TileGenData(); - // temporary flag for map. - private boolean occupied; - - - public Tile(int id) { - this(Tiles.get(id)); - } + protected final TileRenderer renderer; + public final int id; - public Tile(TileModel model) { - setModel(model); - } + protected final Stack items = new Stack<>(); - public Tile() { - } + // temporary flag for map. + protected boolean occupied; + protected boolean explored; - private void setModel(TileModel model) + public Tile(int id, TileRenderer renderer) { - this.model = model; - this.id = model.id; - this.renderer = model.renderer; + this.id = id; + this.renderer = renderer; } /** - * Render the tile alone (must not use other than the main map texture) + * Render the tile, using the main texture sheet. */ - public void renderTile(TileRenderContext context) - { - renderer.render(context); - - if (hasItems()) { - renderer.renderItemOnTile(items.peek(), context); - } - } + public abstract void renderTile(TileRenderContext context); /** - * Render items + * Render extra stuff (ie. dropped items).
+ * Called after the whole map is rendered using renderTile. * * @param context */ - public void renderItems(TileRenderContext context) - { - if (hasItems()) { - renderer.renderItemOnTile(items.peek(), context); - } - } + public abstract void renderExtra(TileRenderContext context); @Override public void save(IonOutput out) throws IOException { - out.writeIntByte(id); - - if (model.hasDroppedItems()) { - out.writeSequence(items); - } - - data.save(out); + out.writeBoolean(explored); } @Override public void load(IonInput in) throws IOException { - id = in.readIntByte(); - - // if model changed - if (model == null || id != model.id) { - setModel(Tiles.get(id)); - } - - if (model.hasDroppedItems()) { - in.readSequence(items); - } - - data.load(in); + explored = in.readBoolean(); } - /** - * Update tile logic state (on server) - * - * @param level the level - * @param delta delta time - */ - public void update(Level level, double delta) + public final boolean isOccupied() { - model.update(this, level, delta); + return occupied; } - public boolean isWalkable() + public final void setOccupied(boolean occupied) { - return model.isWalkable(this); + this.occupied = occupied; } - public boolean isDoor() + public final boolean isExplored() { - return model.isDoor(); + return explored; } - public boolean isNull() + public void setExplored() { - return model.isNullTile(); + explored = true; } - public TileModel getModel() + public final boolean isNull() { - return model; + return getType() == TileType.NULL; } - public boolean hasItems() + public final boolean isWall() { - return model.hasDroppedItems() && !items.isEmpty(); + return getType() == TileType.WALL; } - public boolean doesCastShadow() + public final boolean isFloor() { - return model.doesCastShadow(); + return getType() == TileType.FLOOR; } - @Override - public short getIonMark() + public final boolean isDoor() { - return ION_MARK; + return getType() == TileType.DOOR; } - public boolean isOccupied() - { - return occupied; - } + public abstract void update(Level level, double delta); - public void setOccupied(boolean occupied) - { - this.occupied = occupied; - } + public abstract boolean isWalkable(); - public boolean isWall() - { - return model.isWall(); - } + public abstract boolean isPotentiallyWalkable(); - public boolean isFloor() - { - return model.isFloor(); - } + public abstract TileType getType(); - public boolean isPotentiallyWalkable() - { - return model.isPotentiallyWalkable(); - } + public abstract boolean canHaveItems(); - public Color getMapColor() - { - return model.getMapColor(this); - } + public abstract boolean doesCastShadow(); - public boolean isExplored() - { - return data.explored; - } + public abstract boolean doesReceiveShadow(); - public void explore() - { - data.explored = true; - } - - - public boolean doesReceiveShadow() - { - return model.doesReceiveShadow(); - } + public abstract Color getMapColor(); + } diff --git a/src/mightypork/rogue/world/tile/TileData.java b/src/mightypork/rogue/world/tile/TileData.java deleted file mode 100644 index 6bd1902..0000000 --- a/src/mightypork/rogue/world/tile/TileData.java +++ /dev/null @@ -1,54 +0,0 @@ -package mightypork.rogue.world.tile; - - -import java.io.IOException; - -import mightypork.util.error.YouFuckedUpException; -import mightypork.util.files.ion.IonBinary; -import mightypork.util.files.ion.IonBundle; -import mightypork.util.files.ion.IonInput; -import mightypork.util.files.ion.IonOutput; - - -public class TileData implements IonBinary { - - private static final byte BIT_EXPLORED = 1 << 0; - private static final byte BIT_LOCKED = 1 << 1; - - public boolean explored = false; - public boolean locked = false; - - public final IonBundle extra = new IonBundle(); - - - @Override - public void load(IonInput in) throws IOException - { - final byte flags = in.readByte(); - in.readBundle(extra); - - explored = (flags & BIT_EXPLORED) != 0; - locked = (flags & BIT_LOCKED) != 0; - } - - - @Override - public void save(IonOutput out) throws IOException - { - byte flags = 0; - if (explored) flags |= BIT_EXPLORED; - if (locked) flags |= BIT_LOCKED; - out.writeByte(flags); - - - out.writeBundle(extra); - } - - - @Override - public short getIonMark() - { - throw new YouFuckedUpException("TileData is not to be read from ION using mark."); - } - -} diff --git a/src/mightypork/rogue/world/tile/TileModel.java b/src/mightypork/rogue/world/tile/TileModel.java index 18adb30..04cc856 100644 --- a/src/mightypork/rogue/world/tile/TileModel.java +++ b/src/mightypork/rogue/world/tile/TileModel.java @@ -1,8 +1,9 @@ package mightypork.rogue.world.tile; -import mightypork.rogue.world.level.Level; -import mightypork.util.math.color.Color; +import java.io.IOException; +import mightypork.util.files.ion.IonInput; +import mightypork.util.files.ion.IonOutput; /** @@ -10,79 +11,46 @@ import mightypork.util.math.color.Color; * * @author MightyPork */ -public abstract class TileModel { +public final class TileModel { /** Model ID */ public final int id; - public TileRenderer renderer = TileRenderer.NONE; + public final TileRenderer renderer; + public final Class tileClass; - public TileModel(int id) + public TileModel(int id, Class tile, TileRenderer renderer) { Tiles.register(id, this); this.id = id; - } - - - public TileModel setRenderer(TileRenderer renderer) - { this.renderer = renderer; - return this; + this.tileClass = tile; } /** - * @return new tile of this type; if 100% invariant, can return cached one. + * @return new tile of this type */ public Tile createTile() { - return new Tile(this); + try { + return tileClass.getConstructor(int.class, TileRenderer.class).newInstance(id, renderer); + } catch (Exception e) { + throw new RuntimeException("Could not instantiate a tile.", e); + } } - public abstract boolean isWalkable(Tile tile); - - - public abstract boolean isDoor(); - - - public abstract boolean isWall(); - - - public abstract boolean isFloor(); - - - public abstract boolean doesCastShadow(); - - - public abstract boolean doesReceiveShadow(); - - - public boolean isNullTile() + public Tile loadTile(IonInput in) throws IOException { - return false; + Tile t = createTile(); + t.load(in); + return t; } - /** - * Update tile in world - */ - public abstract void update(Tile tile, Level level, double delta); - - - /** - * @return true if this item can have dropped items - */ - public abstract boolean hasDroppedItems(); - - - /** - * @return true if walkable at some conditions (ie. floor, hidden door, - * locked door etc) - */ - public abstract boolean isPotentiallyWalkable(); - - - public abstract Color getMapColor(Tile tile); - + public void saveTile(IonOutput out, Tile tile) throws IOException + { + tile.save(out); + } } diff --git a/src/mightypork/rogue/world/tile/TileRenderer.java b/src/mightypork/rogue/world/tile/TileRenderer.java index 8359994..1ff8172 100644 --- a/src/mightypork/rogue/world/tile/TileRenderer.java +++ b/src/mightypork/rogue/world/tile/TileRenderer.java @@ -4,9 +4,7 @@ import mightypork.gamecore.render.Render; import mightypork.gamecore.render.textures.TxQuad; import mightypork.rogue.Res; import mightypork.rogue.world.Sides; -import mightypork.rogue.world.item.Item; import mightypork.rogue.world.level.render.TileRenderContext; -import mightypork.rogue.world.tile.renderers.NullTileRenderer; import mightypork.util.math.constraints.rect.Rect; @@ -17,16 +15,12 @@ import mightypork.util.math.constraints.rect.Rect; */ public abstract class TileRenderer { - 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; - private DroppedItemRenderer itemRenderer; - public TileRenderer() { if (!inited) { @@ -51,41 +45,10 @@ public abstract class TileRenderer { } - /** - * Update tile renderer - * - * @param delta delta time - */ - public void update(double delta) - { - if (itemRenderer != null) { - itemRenderer.update(delta); - } - } - - - /** - * Render the tile. - * - * @param context - */ - public final void render(TileRenderContext context) - { - Tile t = context.getTile(); - if (t.isNull() || !t.isExplored()) return; - - renderTile(context); - - if (t.doesReceiveShadow()) renderShadows(context); - - renderUFog(context); - } - - - protected abstract void renderTile(TileRenderContext context); + public abstract void renderTile(TileRenderContext context); - protected void renderShadows(TileRenderContext context) + public void renderShadows(TileRenderContext context) { final TileRenderData trd = context.getTile().renderData; @@ -96,7 +59,7 @@ public abstract class TileRenderer { for (int i = 0; i < 8; i++) { final Tile t2 = context.getAdjacentTile(Sides.get(i)); - if (t2.doesCastShadow()) { + if (!t2.isNull() && t2.doesCastShadow()) { trd.shadows |= Sides.bit(i); } } @@ -120,9 +83,8 @@ public abstract class TileRenderer { } - protected void renderUFog(TileRenderContext context) - { - + public void renderUnexploredFog(TileRenderContext context) + { // TODO cache in tile, update neighbouring tiles upon "explored" flag changed. byte ufog = 0; @@ -150,14 +112,4 @@ public abstract class TileRenderer { if ((ufog & Sides.S) != 0) Render.quadTextured(rect, UFOG_S); if ((ufog & Sides.SE_CORNER) == Sides.SE) Render.quadTextured(rect, UFOG_SE); } - - - public void renderItemOnTile(Item item, TileRenderContext context) - { - if (itemRenderer == null) { - itemRenderer = new DroppedItemRenderer(); - } - - itemRenderer.render(item, context); - } } diff --git a/src/mightypork/rogue/world/tile/TileType.java b/src/mightypork/rogue/world/tile/TileType.java new file mode 100644 index 0000000..d84fa70 --- /dev/null +++ b/src/mightypork/rogue/world/tile/TileType.java @@ -0,0 +1,12 @@ +package mightypork.rogue.world.tile; + + +/** + * Kinds of tiles + * + * @author MightyPork + */ +public enum TileType +{ + NULL, FLOOR, WALL, DOOR; +} diff --git a/src/mightypork/rogue/world/tile/Tiles.java b/src/mightypork/rogue/world/tile/Tiles.java index 39b95d0..234856e 100644 --- a/src/mightypork/rogue/world/tile/Tiles.java +++ b/src/mightypork/rogue/world/tile/Tiles.java @@ -1,11 +1,18 @@ package mightypork.rogue.world.tile; -import mightypork.rogue.world.tile.models.Floor; -import mightypork.rogue.world.tile.models.NullTile; -import mightypork.rogue.world.tile.models.SimpleDoor; -import mightypork.rogue.world.tile.models.Wall; +import java.io.IOException; + import mightypork.rogue.world.tile.renderers.BasicTileRenderer; +import mightypork.rogue.world.tile.renderers.DoorTileRenderer; +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.WallTile; +import mightypork.util.files.ion.IonInput; +import mightypork.util.files.ion.IonOutput; + /** * Tile registry @@ -16,28 +23,12 @@ public final class Tiles { private static final TileModel[] tiles = new TileModel[256]; - public static final TileModel NULL = new NullTile(0); - - public static final TileModel FLOOR_DARK = new Floor(10).setRenderer(new BasicTileRenderer("tile.floor.dark")); - public static final TileModel WALL_BRICK = new Wall(11).setRenderer(new BasicTileRenderer("tile.wall.brick")); - - public static final TileModel DOOR = new SimpleDoor(12); - + public static final TileModel NULL = new TileModel(0, NullTile.class, new NullTileRenderer()); -// public static final TileModel BRICK_FLOOR_VINES = new Floor(2).setTexture("tile.floor.mossy_bricks"); -// public static final TileModel BRICK_WALL_VINES = new Wall(3).setTexture("tile.wall.mossy_bricks"); -// -// public static final TileModel BRICK_FLOOR_RECT = new Floor(4).setTexture("tile.floor.rect_bricks"); -// public static final TileModel BRICK_WALL_SMALL = new Wall(5).setTexture("tile.wall.small_bricks"); -// -// public static final TileModel SANDSTONE_FLOOR = new Floor(6).setTexture("tile.floor.sandstone"); -// public static final TileModel SANDSTONE_WALL = new Wall(7).setTexture("tile.wall.sandstone"); -// -// public static final TileModel BRCOBBLE_FLOOR = new Floor(8).setTexture("tile.floor.brown_cobble"); -// public static final TileModel BRCOBBLE_WALL = new Wall(9).setTexture("tile.wall.brown_cobble"); -// -// public static final TileModel CRYSTAL_FLOOR = new Floor(10).setTexture("tile.floor.crystal"); -// public static final TileModel CRYSTAL_WALL = new Wall(11).setTexture("tile.wall.crystal"); + public static final TileModel FLOOR_DARK = new TileModel(10, FloorTile.class, new BasicTileRenderer("tile.floor.dark")); + public static final TileModel WALL_BRICK = new TileModel(11, WallTile.class, new BasicTileRenderer("tile.wall.brick")); + public static final TileModel DOOR = new TileModel(12, DoorTile.class, new DoorTileRenderer("tile.door.closed", "tile.door.open")); + public static void register(int id, TileModel model) { @@ -57,4 +48,28 @@ public final class Tiles { return m; } + + + public static Tile loadTile(IonInput in) throws IOException + { + int id = in.readIntByte(); + + TileModel model = get(id); + return model.loadTile(in); + } + + + public static void saveTile(IonOutput out, Tile tile) throws IOException + { + out.writeIntByte(tile.id); + + TileModel model = get(tile.id); + model.saveTile(out, tile); + } + + + public static Tile create(int tileId) + { + return get(tileId).createTile(); + } } diff --git a/src/mightypork/rogue/world/tile/models/AbstractNullTile.java b/src/mightypork/rogue/world/tile/models/AbstractNullTile.java deleted file mode 100644 index 99da189..0000000 --- a/src/mightypork/rogue/world/tile/models/AbstractNullTile.java +++ /dev/null @@ -1,53 +0,0 @@ -package mightypork.rogue.world.tile.models; - - -import mightypork.rogue.world.tile.Tile; - - -/** - * Null tile - * - * @author MightyPork - */ -public abstract class AbstractNullTile extends AbstractTile { - - private Tile inst; - - - public AbstractNullTile(int id) - { - super(id); - } - - - @Override - public boolean isNullTile() - { - return true; - } - - - @Override - public Tile createTile() - { - if (inst == null) { - inst = new Tile(this); - } - - return inst; - } - - - @Override - public boolean hasDroppedItems() - { - return false; - } - - - @Override - public boolean doesCastShadow() - { - return false; - } -} diff --git a/src/mightypork/rogue/world/tile/models/AbstractTile.java b/src/mightypork/rogue/world/tile/models/AbstractTile.java deleted file mode 100644 index 37d09df..0000000 --- a/src/mightypork/rogue/world/tile/models/AbstractTile.java +++ /dev/null @@ -1,62 +0,0 @@ -package mightypork.rogue.world.tile.models; - - -import mightypork.rogue.world.level.Level; -import mightypork.rogue.world.tile.Tile; -import mightypork.rogue.world.tile.TileModel; -import mightypork.util.annotations.DefaultImpl; - - -/** - * Basic implementation of a tile. - * - * @author MightyPork - */ -public abstract class AbstractTile extends TileModel { - - public AbstractTile(int id) - { - super(id); - } - - - @Override - public boolean isWalkable(Tile tile) - { - return isPotentiallyWalkable(); - } - - - @Override - public boolean isDoor() - { - return false; - } - - - @Override - public boolean isWall() - { - return false; - } - - - @Override - public boolean isFloor() - { - return false; - } - - @Override - public boolean doesReceiveShadow() - { - return isFloor(); - } - - - @Override - @DefaultImpl - public void update(Tile tile, Level level, double delta) - { - } -} diff --git a/src/mightypork/rogue/world/tile/models/Floor.java b/src/mightypork/rogue/world/tile/models/Floor.java deleted file mode 100644 index 209b30c..0000000 --- a/src/mightypork/rogue/world/tile/models/Floor.java +++ /dev/null @@ -1,50 +0,0 @@ -package mightypork.rogue.world.tile.models; - - -import mightypork.rogue.world.tile.Tile; -import mightypork.util.math.color.Color; -import mightypork.util.math.color.RGB; - - -public class Floor extends AbstractTile { - - public Floor(int id) - { - super(id); - } - - - @Override - public boolean isPotentiallyWalkable() - { - return true; - } - - - @Override - public boolean hasDroppedItems() - { - return true; - } - - - @Override - public boolean doesCastShadow() - { - return false; - } - - - @Override - public boolean isFloor() - { - return true; - } - - - @Override - public Color getMapColor(Tile tile) - { - return RGB.GRAY_DARK; - } -} diff --git a/src/mightypork/rogue/world/tile/models/NullTile.java b/src/mightypork/rogue/world/tile/models/NullTile.java deleted file mode 100644 index 4f2c67c..0000000 --- a/src/mightypork/rogue/world/tile/models/NullTile.java +++ /dev/null @@ -1,29 +0,0 @@ -package mightypork.rogue.world.tile.models; - - -import mightypork.rogue.world.tile.Tile; -import mightypork.util.math.color.Color; -import mightypork.util.math.color.RGB; - - -public class NullTile extends AbstractNullTile { - - public NullTile(int id) - { - super(id); - } - - - @Override - public boolean isPotentiallyWalkable() - { - return false; - } - - - @Override - public Color getMapColor(Tile tile) - { - return RGB.NONE; - } -} diff --git a/src/mightypork/rogue/world/tile/models/SimpleDoor.java b/src/mightypork/rogue/world/tile/models/SimpleDoor.java deleted file mode 100644 index 7bdb025..0000000 --- a/src/mightypork/rogue/world/tile/models/SimpleDoor.java +++ /dev/null @@ -1,65 +0,0 @@ -package mightypork.rogue.world.tile.models; - - -import mightypork.rogue.world.tile.Tile; -import mightypork.rogue.world.tile.renderers.DoorRenderer; -import mightypork.util.math.color.Color; -import mightypork.util.math.color.PAL16; - - -public class SimpleDoor extends AbstractTile { - - public SimpleDoor(int id) - { - super(id); - setRenderer(new DoorRenderer("tile.door.closed", "tile.door.open")); - } - - - @Override - public boolean isPotentiallyWalkable() - { - return true; - } - - - @Override - public boolean isWalkable(Tile tile) - { - return !isLocked(tile); - } - - - protected boolean isLocked(Tile tile) - { - return false; - } - - - @Override - public boolean isDoor() - { - return true; - } - - - @Override - public boolean doesCastShadow() - { - return true; - } - - - @Override - public boolean hasDroppedItems() - { - return false; - } - - - @Override - public Color getMapColor(Tile tile) - { - return PAL16.NEWPOOP; - } -} diff --git a/src/mightypork/rogue/world/tile/models/Wall.java b/src/mightypork/rogue/world/tile/models/Wall.java deleted file mode 100644 index 2d1192c..0000000 --- a/src/mightypork/rogue/world/tile/models/Wall.java +++ /dev/null @@ -1,55 +0,0 @@ -package mightypork.rogue.world.tile.models; - - -import mightypork.rogue.world.tile.Tile; -import mightypork.util.math.color.Color; -import mightypork.util.math.color.RGB; - - -/** - * Template for wall tiles with no metadata - * - * @author MightyPork - */ -public class Wall extends AbstractTile { - - public Wall(int id) - { - super(id); - } - - - @Override - public final boolean hasDroppedItems() - { - return false; - } - - - @Override - public final boolean doesCastShadow() - { - return true; - } - - - @Override - public final boolean isWall() - { - return true; - } - - - @Override - public final boolean isPotentiallyWalkable() - { - return false; - } - - - @Override - public Color getMapColor(Tile tile) - { - return RGB.GRAY_LIGHT; - } -} diff --git a/src/mightypork/rogue/world/tile/renderers/DoorRenderer.java b/src/mightypork/rogue/world/tile/renderers/DoorTileRenderer.java similarity index 87% rename from src/mightypork/rogue/world/tile/renderers/DoorRenderer.java rename to src/mightypork/rogue/world/tile/renderers/DoorTileRenderer.java index 09b483a..86e365c 100644 --- a/src/mightypork/rogue/world/tile/renderers/DoorRenderer.java +++ b/src/mightypork/rogue/world/tile/renderers/DoorTileRenderer.java @@ -10,13 +10,13 @@ import mightypork.rogue.world.tile.TileRenderer; import mightypork.util.math.constraints.rect.Rect; -public class DoorRenderer extends TileRenderer { +public class DoorTileRenderer extends TileRenderer { private final TxQuad closed; private final TxQuad open; - public DoorRenderer(String quadClosed, String quadOpen) + public DoorTileRenderer(String quadClosed, String quadOpen) { this.closed = Res.getTxQuad(quadClosed); this.open = Res.getTxQuad(quadOpen); diff --git a/src/mightypork/rogue/world/tile/renderers/NullTileRenderer.java b/src/mightypork/rogue/world/tile/renderers/NullTileRenderer.java index 71a1a39..e792c0c 100644 --- a/src/mightypork/rogue/world/tile/renderers/NullTileRenderer.java +++ b/src/mightypork/rogue/world/tile/renderers/NullTileRenderer.java @@ -8,7 +8,7 @@ import mightypork.rogue.world.tile.TileRenderer; public class NullTileRenderer extends TileRenderer { @Override - protected void renderTile(TileRenderContext context) + public void renderTile(TileRenderContext context) { } diff --git a/src/mightypork/rogue/world/tile/tiles/BasicTile.java b/src/mightypork/rogue/world/tile/tiles/BasicTile.java new file mode 100644 index 0000000..250ef68 --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/BasicTile.java @@ -0,0 +1,58 @@ +package mightypork.rogue.world.tile.tiles; + + +import mightypork.rogue.world.level.Level; +import mightypork.rogue.world.level.render.TileRenderContext; +import mightypork.rogue.world.tile.Tile; +import mightypork.rogue.world.tile.TileRenderer; +import mightypork.util.annotations.DefaultImpl; + + +public abstract class BasicTile extends Tile { + + public BasicTile(int id, TileRenderer renderer) + { + super(id, renderer); + } + + + @Override + public boolean isWalkable() + { + return isPotentiallyWalkable(); + } + + + @Override + public void renderTile(TileRenderContext context) + { + if (!isExplored()) return; + + renderer.renderTile(context); + + if (doesReceiveShadow()) renderer.renderShadows(context); + + renderer.renderUnexploredFog(context); + } + + + @Override + @DefaultImpl + public void renderExtra(TileRenderContext context) + { + } + + + @Override + @DefaultImpl + public void update(Level level, double delta) + { + } + + + @Override + public boolean doesReceiveShadow() + { + return !doesCastShadow(); + } +} diff --git a/src/mightypork/rogue/world/tile/tiles/DoorTile.java b/src/mightypork/rogue/world/tile/tiles/DoorTile.java new file mode 100644 index 0000000..8fafff7 --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/DoorTile.java @@ -0,0 +1,46 @@ +package mightypork.rogue.world.tile.tiles; + +import mightypork.rogue.world.tile.TileRenderer; +import mightypork.rogue.world.tile.TileType; +import mightypork.util.math.color.Color; +import mightypork.util.math.color.PAL16; + + +public class DoorTile extends BasicTile { + + public DoorTile(int id, TileRenderer renderer) + { + super(id, renderer); + } + + @Override + public boolean isPotentiallyWalkable() + { + return true; + } + + @Override + public TileType getType() + { + return TileType.DOOR; + } + + @Override + public boolean canHaveItems() + { + return false; + } + + @Override + public boolean doesCastShadow() + { + return true; + } + + @Override + public Color getMapColor() + { + return PAL16.NEWPOOP; + } + +} diff --git a/src/mightypork/rogue/world/tile/tiles/FloorTile.java b/src/mightypork/rogue/world/tile/tiles/FloorTile.java new file mode 100644 index 0000000..121600a --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/FloorTile.java @@ -0,0 +1,45 @@ +package mightypork.rogue.world.tile.tiles; + + +import mightypork.rogue.world.tile.TileRenderer; +import mightypork.rogue.world.tile.TileType; +import mightypork.util.math.color.Color; +import mightypork.util.math.color.RGB; + + +public class FloorTile extends TileWithItems { + + public FloorTile(int id, TileRenderer renderer) + { + super(id, renderer); + } + + + @Override + public boolean isPotentiallyWalkable() + { + return true; + } + + + @Override + public TileType getType() + { + return TileType.FLOOR; + } + + + @Override + public boolean doesCastShadow() + { + return false; + } + + + @Override + public Color getMapColor() + { + return RGB.GRAY_DARK; + } + +} diff --git a/src/mightypork/rogue/world/tile/tiles/LockedDoorTile.java b/src/mightypork/rogue/world/tile/tiles/LockedDoorTile.java new file mode 100644 index 0000000..7b1ea96 --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/LockedDoorTile.java @@ -0,0 +1,36 @@ +package mightypork.rogue.world.tile.tiles; + + +import java.io.IOException; + +import mightypork.rogue.world.tile.TileRenderer; +import mightypork.util.files.ion.IonInput; +import mightypork.util.files.ion.IonOutput; + + +public class LockedDoorTile extends DoorTile { + + public boolean locked = true; + + + public LockedDoorTile(int id, TileRenderer renderer) + { + super(id, renderer); + } + + + @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 new file mode 100644 index 0000000..7b683aa --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/NullTile.java @@ -0,0 +1,86 @@ +package mightypork.rogue.world.tile.tiles; + + +import mightypork.rogue.world.level.Level; +import mightypork.rogue.world.level.render.TileRenderContext; +import mightypork.rogue.world.tile.Tile; +import mightypork.rogue.world.tile.TileRenderer; +import mightypork.rogue.world.tile.TileType; +import mightypork.util.math.color.Color; +import mightypork.util.math.color.RGB; + + +public class NullTile extends Tile { + + public NullTile(int id, TileRenderer renderer) + { + super(id, renderer); + } + + + @Override + public void update(Level level, double delta) + { + } + + + @Override + public void renderTile(TileRenderContext context) + { + } + + + @Override + public void renderExtra(TileRenderContext context) + { + } + + + @Override + public boolean isWalkable() + { + return false; + } + + + @Override + public boolean isPotentiallyWalkable() + { + return false; + } + + + @Override + public TileType getType() + { + return TileType.NULL; + } + + + @Override + public boolean canHaveItems() + { + return false; + } + + + @Override + public boolean doesCastShadow() + { + return false; + } + + + @Override + public boolean doesReceiveShadow() + { + return false; + } + + + @Override + public Color getMapColor() + { + return RGB.NONE; + } +} diff --git a/src/mightypork/rogue/world/tile/tiles/TileWithItems.java b/src/mightypork/rogue/world/tile/tiles/TileWithItems.java new file mode 100644 index 0000000..24dddf5 --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/TileWithItems.java @@ -0,0 +1,64 @@ +package mightypork.rogue.world.tile.tiles; + + +import java.io.IOException; + +import mightypork.rogue.world.level.Level; +import mightypork.rogue.world.level.render.TileRenderContext; +import mightypork.rogue.world.tile.DroppedItemRenderer; +import mightypork.rogue.world.tile.TileRenderer; +import mightypork.util.files.ion.IonInput; +import mightypork.util.files.ion.IonOutput; + + +public abstract class TileWithItems extends BasicTile { + + private DroppedItemRenderer itemRenderer = new DroppedItemRenderer(); + + + public TileWithItems(int id, TileRenderer renderer) + { + super(id, renderer); + } + + + @Override + public void renderExtra(TileRenderContext context) + { + if (!items.isEmpty()) { + itemRenderer.render(items.peek(), context); + } + } + + + @Override + public void update(Level level, double delta) + { + itemRenderer.update(delta); + } + + + @Override + public boolean canHaveItems() + { + return true; + } + + + @Override + public void save(IonOutput out) throws IOException + { + super.save(out); + + out.writeSequence(items); + } + + + @Override + public void load(IonInput in) throws IOException + { + super.load(in); + + in.readSequence(items); + } +} diff --git a/src/mightypork/rogue/world/tile/tiles/WallTile.java b/src/mightypork/rogue/world/tile/tiles/WallTile.java new file mode 100644 index 0000000..6f74737 --- /dev/null +++ b/src/mightypork/rogue/world/tile/tiles/WallTile.java @@ -0,0 +1,46 @@ +package mightypork.rogue.world.tile.tiles; + +import mightypork.rogue.world.tile.TileRenderer; +import mightypork.rogue.world.tile.TileType; +import mightypork.util.math.color.Color; +import mightypork.util.math.color.RGB; + + +public class WallTile extends BasicTile { + + public WallTile(int id, TileRenderer renderer) + { + super(id, renderer); + } + + @Override + public boolean isPotentiallyWalkable() + { + return false; + } + + @Override + public TileType getType() + { + return TileType.WALL; + } + + @Override + public boolean canHaveItems() + { + return false; + } + + @Override + public boolean doesCastShadow() + { + return true; + } + + @Override + public Color getMapColor() + { + return RGB.GRAY_LIGHT; + } + +} diff --git a/src/mightypork/util/files/ion/IonBinary.java b/src/mightypork/util/files/ion/IonBinary.java index a58abf2..455918b 100644 --- a/src/mightypork/util/files/ion/IonBinary.java +++ b/src/mightypork/util/files/ion/IonBinary.java @@ -5,30 +5,11 @@ import java.io.IOException; /** - * Binary ion object + * Binary ion object, with a mark = saveable / loadable on it's own * * @author MightyPork */ -public interface IonBinary { - - /** - * Load data from the input stream. - * - * @param in input stream - * @throws IOException - */ - void load(IonInput in) throws IOException; - - - /** - * Store data to output stream (in such way that the load method will later - * be able to read it). - * - * @param out Output stream - * @throws IOException - */ - void save(IonOutput out) throws IOException; - +public interface IonBinary extends IonBinaryHeadless { /** * Get Ion mark byte. diff --git a/src/mightypork/util/files/ion/IonBinaryHeadless.java b/src/mightypork/util/files/ion/IonBinaryHeadless.java new file mode 100644 index 0000000..fec0ef9 --- /dev/null +++ b/src/mightypork/util/files/ion/IonBinaryHeadless.java @@ -0,0 +1,31 @@ +package mightypork.util.files.ion; + + +import java.io.IOException; + + +/** + * Binary ion object, with no mark = cannot be loaded on it's own + * + * @author MightyPork + */ +public interface IonBinaryHeadless { + + /** + * Load data from the input stream. + * + * @param in input stream + * @throws IOException + */ + void load(IonInput in) throws IOException; + + + /** + * Store data to output stream (in such way that the load method will later + * be able to read it). + * + * @param out Output stream + * @throws IOException + */ + void save(IonOutput out) throws IOException; +}