From e782b31cacccb0a96c94ddd600ba48930b9380c7 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Sat, 3 Dec 2016 02:47:35 -0500 Subject: [PATCH] v0.5.0: initial implementation of new game visuals Very messy, crashes outside of sewers, more work needed. --- core/src/main/assets/tiles_sewer.png | Bin 0 -> 42733 bytes .../shatteredpixeldungeon/Assets.java | 2 +- .../shatteredpixeldungeon/DungeonTilemap.java | 166 +++++++++++------- .../scenes/GameScene.java | 8 + .../tiles/DungeonTileSheet.java | 132 ++++++++++++++ .../ui/DungeonWallsTilemap.java | 162 +++++++++++++++++ 6 files changed, 406 insertions(+), 64 deletions(-) create mode 100644 core/src/main/assets/tiles_sewer.png create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/DungeonTileSheet.java create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/DungeonWallsTilemap.java diff --git a/core/src/main/assets/tiles_sewer.png b/core/src/main/assets/tiles_sewer.png new file mode 100644 index 0000000000000000000000000000000000000000..d2d995146f8f4337e2bbe07371c9f0afb75b43a4 GIT binary patch literal 42733 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 SqH=-2M_pO_PLUEK^gjSHOPmG( literal 0 HcmV?d00001 diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java index 9ad977ae9..0c9b741f3 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java @@ -100,7 +100,7 @@ public class Assets { public static final String ITEMS = "items.png"; public static final String TERRAIN_FEATURES = "terrain_features.png"; - public static final String TILES_SEWERS = "tiles0.png"; + public static final String TILES_SEWERS = "tiles_sewer.png"; public static final String TILES_PRISON = "tiles1.png"; public static final String TILES_CAVES = "tiles2.png"; public static final String TILES_CITY = "tiles3.png"; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/DungeonTilemap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/DungeonTilemap.java index c6b55917e..a76945584 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/DungeonTilemap.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/DungeonTilemap.java @@ -24,6 +24,7 @@ import android.util.SparseIntArray; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; +import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTileSheet; import com.watabou.noosa.Image; import com.watabou.noosa.TextureFilm; import com.watabou.noosa.Tilemap; @@ -45,59 +46,59 @@ public class DungeonTilemap extends Tilemap { //Used to map dungeon tiles to their default visual values public static SparseIntArray defaultVisuals = new SparseIntArray(32); static { - defaultVisuals.put(Terrain.CHASM, 0); - defaultVisuals.put(Terrain.EMPTY, 1); - defaultVisuals.put(Terrain.GRASS, 2); - defaultVisuals.put(Terrain.EMPTY_WELL, 3); - defaultVisuals.put(Terrain.WALL, 4); - defaultVisuals.put(Terrain.DOOR, 5); - defaultVisuals.put(Terrain.OPEN_DOOR, 6); - defaultVisuals.put(Terrain.ENTRANCE, 7); - defaultVisuals.put(Terrain.EXIT, 8); - defaultVisuals.put(Terrain.EMBERS, 9); - defaultVisuals.put(Terrain.LOCKED_DOOR, 10); - defaultVisuals.put(Terrain.PEDESTAL, 11); - defaultVisuals.put(Terrain.WALL_DECO, 12); - defaultVisuals.put(Terrain.BARRICADE, 13); - defaultVisuals.put(Terrain.EMPTY_SP, 14); - defaultVisuals.put(Terrain.HIGH_GRASS, 15); + defaultVisuals.put(Terrain.CHASM, DungeonTileSheet.CHASM); + defaultVisuals.put(Terrain.EMPTY, DungeonTileSheet.FLOOR); + defaultVisuals.put(Terrain.GRASS, DungeonTileSheet.GRASS); + defaultVisuals.put(Terrain.EMPTY_WELL, DungeonTileSheet.EMPTY_WELL); + defaultVisuals.put(Terrain.WALL, DungeonTileSheet.FLAT_WALL); + defaultVisuals.put(Terrain.DOOR, DungeonTileSheet.FLAT_DOOR); + defaultVisuals.put(Terrain.OPEN_DOOR, DungeonTileSheet.FLAT_DOOR_OPEN); + defaultVisuals.put(Terrain.ENTRANCE, DungeonTileSheet.ENTRANCE); + defaultVisuals.put(Terrain.EXIT, DungeonTileSheet.EXIT); + defaultVisuals.put(Terrain.EMBERS, DungeonTileSheet.EMBERS); + defaultVisuals.put(Terrain.LOCKED_DOOR, DungeonTileSheet.FLAT_DOOR_LOCKED); + defaultVisuals.put(Terrain.PEDESTAL, DungeonTileSheet.PEDESTAL); + defaultVisuals.put(Terrain.WALL_DECO, DungeonTileSheet.FLAT_WALL_DECO); + defaultVisuals.put(Terrain.BARRICADE, DungeonTileSheet.BARRICADE); + defaultVisuals.put(Terrain.EMPTY_SP, DungeonTileSheet.FLOOR_SP); + defaultVisuals.put(Terrain.HIGH_GRASS, DungeonTileSheet.HIGH_GRASS); defaultVisuals.put(Terrain.SECRET_DOOR, defaultVisuals.get(Terrain.WALL)); defaultVisuals.put(Terrain.SECRET_TRAP, defaultVisuals.get(Terrain.EMPTY)); defaultVisuals.put(Terrain.TRAP, defaultVisuals.get(Terrain.EMPTY)); defaultVisuals.put(Terrain.INACTIVE_TRAP, defaultVisuals.get(Terrain.EMPTY)); - defaultVisuals.put(Terrain.EMPTY_DECO, 16); - defaultVisuals.put(Terrain.LOCKED_EXIT, 17); - defaultVisuals.put(Terrain.UNLOCKED_EXIT, 18); - defaultVisuals.put(Terrain.SIGN, 19); - defaultVisuals.put(Terrain.WELL, 20); - defaultVisuals.put(Terrain.STATUE, 21); - defaultVisuals.put(Terrain.STATUE_SP, 22); - defaultVisuals.put(Terrain.BOOKSHELF, 23); - defaultVisuals.put(Terrain.ALCHEMY, 24); + defaultVisuals.put(Terrain.EMPTY_DECO, DungeonTileSheet.FLOOR_DECO); + defaultVisuals.put(Terrain.LOCKED_EXIT, DungeonTileSheet.LOCKED_EXIT); + defaultVisuals.put(Terrain.UNLOCKED_EXIT, DungeonTileSheet.UNLOCKED_EXIT); + defaultVisuals.put(Terrain.SIGN, DungeonTileSheet.SIGN); + defaultVisuals.put(Terrain.WELL, DungeonTileSheet.WELL); + defaultVisuals.put(Terrain.STATUE, DungeonTileSheet.STATUE); + defaultVisuals.put(Terrain.STATUE_SP, DungeonTileSheet.STATUE_SP); + defaultVisuals.put(Terrain.BOOKSHELF, DungeonTileSheet.BOOKSHELF); + defaultVisuals.put(Terrain.ALCHEMY, DungeonTileSheet.ALCHEMY_POT); - defaultVisuals.put(Terrain.WATER, 63); + defaultVisuals.put(Terrain.WATER, DungeonTileSheet.WATER); } //These alt visuals will trigger 50% of the time public static SparseIntArray commonAltVisuals = new SparseIntArray(32); static { - commonAltVisuals.put(1, 38); - commonAltVisuals.put(2, 39); - commonAltVisuals.put(4, 40); - commonAltVisuals.put(9, 41); - commonAltVisuals.put(12, 42); - commonAltVisuals.put(14, 43); - commonAltVisuals.put(15, 44); - commonAltVisuals.put(16, 45); - commonAltVisuals.put(23, 46); + commonAltVisuals.put(DungeonTileSheet.FLOOR, DungeonTileSheet.FLOOR_ALT_1); + commonAltVisuals.put(DungeonTileSheet.GRASS, DungeonTileSheet.GRASS_ALT); + commonAltVisuals.put(DungeonTileSheet.FLAT_WALL, DungeonTileSheet.FLAT_WALL_ALT); + commonAltVisuals.put(DungeonTileSheet.EMBERS, DungeonTileSheet.EMBERS_ALT); + commonAltVisuals.put(DungeonTileSheet.FLAT_WALL_DECO, DungeonTileSheet.FLAT_WALL_DECO_ALT); + commonAltVisuals.put(DungeonTileSheet.FLOOR_SP, DungeonTileSheet.FLOOR_SP_ALT); + commonAltVisuals.put(DungeonTileSheet.HIGH_GRASS, DungeonTileSheet.HIGH_GRASS_ALT); + commonAltVisuals.put(DungeonTileSheet.FLOOR_DECO, DungeonTileSheet.FLOOR_DECO_ALT); + commonAltVisuals.put(DungeonTileSheet.BOOKSHELF, DungeonTileSheet.BOOKSHELF_ALT); } //These alt visuals trigger 10% of the time (and also override common alts when they show up) public static SparseIntArray rareAltVisuals = new SparseIntArray(32); static { - rareAltVisuals.put(1, 47); + rareAltVisuals.put(DungeonTileSheet.FLOOR, DungeonTileSheet.FLOOR_ALT_2); } //These tiles can stitch with water @@ -106,35 +107,36 @@ public class DungeonTilemap extends Tilemap { Terrain.ENTRANCE, Terrain.EXIT, Terrain.EMBERS, Terrain.BARRICADE, Terrain.HIGH_GRASS, Terrain.SECRET_TRAP, Terrain.TRAP, Terrain.INACTIVE_TRAP, Terrain.EMPTY_DECO, - Terrain.SIGN, Terrain.WELL, Terrain.STATUE, Terrain.ALCHEMY + Terrain.SIGN, Terrain.WELL, Terrain.STATUE, Terrain.ALCHEMY, + Terrain.DOOR, Terrain.OPEN_DOOR, Terrain.LOCKED_DOOR ); //tiles that can stitch with chasms (from above), and which visual represents the stitching public static SparseIntArray chasmStitcheable = new SparseIntArray(32); static { //floor - chasmStitcheable.put( Terrain.EMPTY, 32 ); - chasmStitcheable.put( Terrain.GRASS, 32 ); - chasmStitcheable.put( Terrain.EMPTY_WELL, 32 ); - chasmStitcheable.put( Terrain.HIGH_GRASS, 32 ); - chasmStitcheable.put( Terrain.EMPTY_DECO, 32 ); - chasmStitcheable.put( Terrain.SIGN, 32 ); - chasmStitcheable.put( Terrain.EMPTY_WELL, 32 ); - chasmStitcheable.put( Terrain.STATUE, 32 ); + chasmStitcheable.put( Terrain.EMPTY, DungeonTileSheet.CHASM_FLOOR ); + chasmStitcheable.put( Terrain.GRASS, DungeonTileSheet.CHASM_FLOOR ); + chasmStitcheable.put( Terrain.EMPTY_WELL, DungeonTileSheet.CHASM_FLOOR ); + chasmStitcheable.put( Terrain.HIGH_GRASS, DungeonTileSheet.CHASM_FLOOR ); + chasmStitcheable.put( Terrain.EMPTY_DECO, DungeonTileSheet.CHASM_FLOOR ); + chasmStitcheable.put( Terrain.SIGN, DungeonTileSheet.CHASM_FLOOR ); + chasmStitcheable.put( Terrain.EMPTY_WELL, DungeonTileSheet.CHASM_FLOOR ); + chasmStitcheable.put( Terrain.STATUE, DungeonTileSheet.CHASM_FLOOR ); //special floor - chasmStitcheable.put( Terrain.EMPTY_SP, 33 ); - chasmStitcheable.put( Terrain.STATUE_SP, 33 ); + chasmStitcheable.put( Terrain.EMPTY_SP, DungeonTileSheet.CHASM_FLOOR_SP ); + chasmStitcheable.put( Terrain.STATUE_SP, DungeonTileSheet.CHASM_FLOOR_SP ); //wall - chasmStitcheable.put( Terrain.WALL, 34 ); - chasmStitcheable.put( Terrain.DOOR, 34 ); - chasmStitcheable.put( Terrain.OPEN_DOOR, 34 ); - chasmStitcheable.put( Terrain.LOCKED_DOOR, 34 ); - chasmStitcheable.put( Terrain.WALL_DECO, 34 ); + chasmStitcheable.put( Terrain.WALL, DungeonTileSheet.CHASM_WALL ); + chasmStitcheable.put( Terrain.DOOR, DungeonTileSheet.CHASM_WALL ); + chasmStitcheable.put( Terrain.OPEN_DOOR, DungeonTileSheet.CHASM_WALL ); + chasmStitcheable.put( Terrain.LOCKED_DOOR, DungeonTileSheet.CHASM_WALL ); + chasmStitcheable.put( Terrain.WALL_DECO, DungeonTileSheet.CHASM_WALL ); //water - chasmStitcheable.put( Terrain.WATER, 35 ); + chasmStitcheable.put( Terrain.WATER, DungeonTileSheet.CHASM_WATER ); } private int[] map; @@ -168,7 +170,7 @@ public class DungeonTilemap extends Tilemap { public synchronized void updateMap() { super.updateMap(); for (int i = 0; i < data.length; i++) - data[i] = getTileVisual(i ,map[i]); + data[i] = getTileVisual(i ,map[i], false); } @Override @@ -178,31 +180,69 @@ public class DungeonTilemap extends Tilemap { super.updateMapCell(cell - mapWidth - 1); super.updateMapCell(cell + mapWidth + 1); for (int i : PathFinder.NEIGHBOURS9) - data[cell + i] = getTileVisual(cell + i, map[cell + i]); + data[cell + i] = getTileVisual(cell + i, map[cell + i], false); //unless we're at the level's edge, then just do the one tile. } else { super.updateMapCell(cell); - data[cell] = getTileVisual(cell, map[cell]); + data[cell] = getTileVisual(cell, map[cell], false); } } - private int getTileVisual(int pos, int tile){ + //These tiles count as wall for the purposes of wall stitching + public static List wallStitcheable = Arrays.asList( + Terrain.WALL, Terrain.WALL_DECO, Terrain.SECRET_DOOR, + Terrain.LOCKED_EXIT, Terrain.UNLOCKED_EXIT + ); + + private int getTileVisual(int pos, int tile, boolean flat) { int visual = defaultVisuals.get(tile); - if (tile == Terrain.WATER){ - for (int i = 0; i < PathFinder.CIRCLE4.length; i++){ + if (tile == Terrain.WATER) { + for (int i = 0; i < PathFinder.CIRCLE4.length; i++) { if (waterStitcheable.contains(map[pos + PathFinder.CIRCLE4[i]])) { - //equivalent to: cell -= 2^i - visual -= (1 << i); + //equivalent to: cell += 2^i + visual += (1 << i); } } return visual; } else if (tile == Terrain.CHASM && pos >= mapWidth) { return chasmStitcheable.get(map[pos - mapWidth], visual); + } - } else if (tileVariance[pos] > 0.9f + if (!flat) { + if ((tile == Terrain.DOOR || tile == Terrain.LOCKED_DOOR || tile == Terrain.OPEN_DOOR) && map[pos - mapWidth] == Terrain.WALL) { + return DungeonTileSheet.RAISED_DOOR_SIDEWAYS; + } else if (tile == Terrain.DOOR) { + return DungeonTileSheet.RAISED_DOOR; + } else if (tile == Terrain.OPEN_DOOR) { + return DungeonTileSheet.RAISED_DOOR_OPEN; + } else if (tile == Terrain.LOCKED_DOOR) { + return DungeonTileSheet.RAISED_DOOR_LOCKED; + } else if (tile == Terrain.WALL || tile == Terrain.WALL_DECO){ + if (tile == Terrain.WALL) { + if (pos + mapWidth < size && (map[pos + mapWidth] == Terrain.DOOR || map[pos + mapWidth] == Terrain.LOCKED_DOOR || map[pos + mapWidth] == Terrain.OPEN_DOOR)){ + visual = DungeonTileSheet.RAISED_WALL_DOOR; + } else { + visual = DungeonTileSheet.RAISED_WALL; + } + } else + visual = DungeonTileSheet.RAISED_WALL_DECO; + + if (tileVariance[pos] > 0.5f) + visual += 16; + + if (pos % mapWidth != 0 && !wallStitcheable.contains(map[pos - 1])) + visual += 2; + if (pos % mapWidth != mapWidth-1 && !wallStitcheable.contains(map[pos + 1])) + visual += 1; + + return visual; + } + } + + if (tileVariance[pos] > 0.9f && rareAltVisuals.indexOfKey(visual) >= 0){ return rareAltVisuals.get(visual); @@ -259,7 +299,7 @@ public class DungeonTilemap extends Tilemap { public static Image tile( int pos, int tile ) { Image img = new Image( instance.texture ); - img.frame( instance.tileset.get( instance.getTileVisual( pos, tile ) ) ); + img.frame( instance.tileset.get( instance.getTileVisual( pos, tile, true ) ) ); return img; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java index e34d6622b..d5c113357 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java @@ -63,6 +63,7 @@ import com.shatteredpixel.shatteredpixeldungeon.ui.AttackIndicator; import com.shatteredpixel.shatteredpixeldungeon.ui.Banner; import com.shatteredpixel.shatteredpixeldungeon.ui.BusyIndicator; import com.shatteredpixel.shatteredpixeldungeon.ui.CustomTileVisual; +import com.shatteredpixel.shatteredpixeldungeon.ui.DungeonWallsTilemap; import com.shatteredpixel.shatteredpixeldungeon.ui.GameLog; import com.shatteredpixel.shatteredpixeldungeon.ui.HealthIndicator; import com.shatteredpixel.shatteredpixeldungeon.ui.LootIndicator; @@ -111,6 +112,7 @@ public class GameScene extends PixelScene { private SkinnedBlock water; private DungeonTilemap tiles; private TerrainFeaturesTilemap terrainFeatures; + private DungeonWallsTilemap walls; private FogOfWar fog; private HeroSprite hero; @@ -233,6 +235,9 @@ public class GameScene extends PixelScene { addBlobSprite( blob ); } + walls = new DungeonWallsTilemap(); + add(walls); + fog = new FogOfWar( Dungeon.level.width(), Dungeon.level.height() ); add( fog ); @@ -675,6 +680,7 @@ public class GameScene extends PixelScene { if (scene != null) { scene.tiles.map(Dungeon.level.map, Dungeon.level.width() ); scene.terrainFeatures.map(Dungeon.level.map, Dungeon.level.width() ); + scene.walls.map(Dungeon.level.map, Dungeon.level.width() ); } updateFog(); } @@ -684,6 +690,7 @@ public class GameScene extends PixelScene { if (scene != null) { scene.tiles.updateMap(); scene.terrainFeatures.updateMap(); + scene.walls.updateMap(); } } @@ -691,6 +698,7 @@ public class GameScene extends PixelScene { if (scene != null) { scene.tiles.updateMapCell( cell ); scene.terrainFeatures.updateMapCell( cell ); + scene.walls.updateMapCell( cell ); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/DungeonTileSheet.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/DungeonTileSheet.java new file mode 100644 index 000000000..7639206db --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/DungeonTileSheet.java @@ -0,0 +1,132 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2016 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.shatteredpixel.shatteredpixeldungeon.tiles; + +public class DungeonTileSheet { + + private static final int WIDTH = 16; + + private static int xy(int x, int y){ + x -= 1; y -= 1; + return x + WIDTH*y; + } + + private static final int GROUND = xy(1, 1); //32 slots + public static final int FLOOR = GROUND +0; + public static final int FLOOR_DECO = GROUND +1; + public static final int HIGH_GRASS = GROUND +2; + public static final int GRASS = GROUND +3; + public static final int EMBERS = GROUND +4; + public static final int FLOOR_SP = GROUND +5; + + public static final int FLOOR_ALT_1 = GROUND +7; + public static final int FLOOR_DECO_ALT = GROUND +8; + public static final int HIGH_GRASS_ALT = GROUND +9; + public static final int GRASS_ALT = GROUND +10; + public static final int EMBERS_ALT = GROUND +11; + public static final int FLOOR_SP_ALT = GROUND +12; + + public static final int FLOOR_ALT_2 = GROUND +14; + + public static final int ENTRANCE = GROUND +16; + public static final int EXIT = GROUND +17; + public static final int SIGN = GROUND +18; + public static final int STATUE = GROUND +19; + public static final int STATUE_SP = GROUND +20; + public static final int WELL = GROUND +21; + public static final int EMPTY_WELL = GROUND +22; + public static final int ALCHEMY_POT = GROUND +23; + public static final int PEDESTAL = GROUND +24; + public static final int BARRICADE = GROUND +25; + public static final int BOOKSHELF = GROUND +26; + + public static final int BOOKSHELF_ALT = GROUND +28; + + + public static final int WATER = xy(1, 3); //16 slots + //next 15 slots are all water stitching with ground. + //+1 for ground above, +2 for ground right, +4 for ground below, +8 for ground left. + + + public static final int CHASM = xy(1, 4); //16 tiles + //chasm stitching visuals... + public static final int CHASM_FLOOR = CHASM+1; + public static final int CHASM_FLOOR_SP = CHASM+2; + public static final int CHASM_WALL = CHASM+3; + public static final int CHASM_WATER = CHASM+4; + + /* + These tiles present wall visuals as flat + */ + private static final int FLAT_WALLS = xy(1, 5); //16 slots + public static final int FLAT_WALL = FLAT_WALLS+0; + public static final int FLAT_WALL_DECO = FLAT_WALLS+1; + + public static final int FLAT_WALL_ALT = FLAT_WALLS+3; + public static final int FLAT_WALL_DECO_ALT = FLAT_WALLS+4; + + private static final int FLAT_DOORS = xy(1,6); //16 slots + public static final int FLAT_DOOR = FLAT_DOORS+0; + public static final int FLAT_DOOR_OPEN = FLAT_DOORS+1; + public static final int FLAT_DOOR_LOCKED = FLAT_DOORS+2; + public static final int UNLOCKED_EXIT = FLAT_DOORS+3; + public static final int LOCKED_EXIT = FLAT_DOORS+4; + + + /* + These tiles present visuals that are raised and rendered on the lower layer (behind characters) + */ + private static final int RAISED_WALLS = xy(1, 8); //32 slots + //+1 for walls to the right, +2 for walls to the left + public static final int RAISED_WALL = RAISED_WALLS+0; + public static final int RAISED_WALL_DECO = RAISED_WALLS+4; + //wall that appears behind a top/bottom doorway + public static final int RAISED_WALL_DOOR = RAISED_WALLS+8; + + public static final int RAISED_WALL_ALT = RAISED_WALLS+16; + public static final int RAISED_WALL_DECO_ALT = RAISED_WALLS+20; + + private static final int RAISED_DOORS = xy(1, 10); //16 slots + public static final int RAISED_DOOR = RAISED_DOORS+0; + public static final int RAISED_DOOR_OPEN = RAISED_DOORS+1; + public static final int RAISED_DOOR_LOCKED = RAISED_DOORS+2; + //floor tile that appears on a top/bottom doorway + public static final int RAISED_DOOR_SIDEWAYS = RAISED_DOORS+3; + + /* + These tiles present visuals that are raised and rendered on the upper layer (above characters) + */ + //+1 for wall right, +2 for wall right-below, +4 for wall left-below, +8 for wall left. + public static final int WALLS_INTERNAL = xy(1, 12); //16 slots + + //+1 for walls to the down-right, +2 for walls to the down-left + private static final int WALLS_OVERHANG = xy(1, 13); //16 slots + public static final int WALL_OVERHANG = WALLS_OVERHANG+0; + public static final int DOOR_SIDEWAYS_OVERHANG = WALL_OVERHANG+4; + public static final int DOOR_SIDEWAYS_OVERHANG_OPEN = WALL_OVERHANG+8; + //no attachment to adjacent walls + public static final int DOOR_OVERHANG = WALL_OVERHANG+12; + public static final int DOOR_OVERHANG_OPEN = WALL_OVERHANG+13; + public static final int DOOR_SIDEWAYS = WALL_OVERHANG+14; + public static final int DOOR_SIDEWAYS_LOCKED = WALL_OVERHANG+15; + + +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/DungeonWallsTilemap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/DungeonWallsTilemap.java new file mode 100644 index 000000000..d407ddb83 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/DungeonWallsTilemap.java @@ -0,0 +1,162 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2016 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.shatteredpixel.shatteredpixeldungeon.ui; + +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; +import com.shatteredpixel.shatteredpixeldungeon.levels.traps.Trap; +import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTileSheet; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.Tilemap; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; + +import java.util.Arrays; +import java.util.List; + +public class DungeonWallsTilemap extends Tilemap { + + public static final int SIZE = 16; + + private static DungeonWallsTilemap instance; + + //These tiles count as wall for the purposes of wall stitching + public static List wallStitcheable = Arrays.asList( + Terrain.WALL, Terrain.WALL_DECO, Terrain.SECRET_DOOR, + Terrain.LOCKED_EXIT, Terrain.UNLOCKED_EXIT + ); + + private int[] map; + private float[] tileVariance; + + public DungeonWallsTilemap(){ + super( + Dungeon.level.tilesTex(), + new TextureFilm( Dungeon.level.tilesTex(), SIZE, SIZE ) ); + + Random.seed( Dungeon.seedCurDepth()); + tileVariance = new float[Dungeon.level.map.length]; + for (int i = 0; i < tileVariance.length; i++) + tileVariance[i] = Random.Float(); + Random.seed(); + + map( Dungeon.level.map, Dungeon.level.width() ); + + instance = this; + } + + @Override + //we need to retain two arrays, map is the dungeon tilemap which we can reference. + // Data is our own internal image representation of the tiles, which may differ. + public void map(int[] data, int cols) { + map = data; + super.map(new int[data.length], cols); + } + + @Override + public synchronized void updateMap() { + super.updateMap(); + for (int i = 0; i < data.length; i++) + data[i] = getTileVisual(i ,map[i]); + } + + @Override + public synchronized void updateMapCell(int cell) { + //update in a 3x3 grid to account for neighbours which might also be affected + if (Dungeon.level.insideMap(cell)) { + super.updateMapCell(cell - mapWidth - 1); + super.updateMapCell(cell + mapWidth + 1); + for (int i : PathFinder.NEIGHBOURS9) + data[cell + i] = getTileVisual(cell + i, map[cell + i]); + + //unless we're at the level's edge, then just do the one tile. + } else { + super.updateMapCell(cell); + data[cell] = getTileVisual(cell, map[cell]); + } + } + + private int getTileVisual(int pos, int tile){ + + if (wallStitcheable.contains(tile)) { + if (pos + mapWidth < size && !wallStitcheable.contains(map[pos + mapWidth])){ + + if (map[pos + mapWidth] == Terrain.DOOR){ + return DungeonTileSheet.DOOR_SIDEWAYS; + } else if (map[pos + mapWidth] == Terrain.LOCKED_DOOR){ + return DungeonTileSheet.DOOR_SIDEWAYS_LOCKED; + } + + } else { + //otherwise, need to stitch with right, bottom-right, bottom-left, and left. + int visual = DungeonTileSheet.WALLS_INTERNAL; + if (pos % mapWidth != 0 && !wallStitcheable.contains(map[pos - 1])) + visual += 8; + if (pos % mapWidth != 0 && pos + mapWidth < size && !wallStitcheable.contains(map[pos - 1 + mapWidth])) + visual += 4; + if ((pos+1) % mapWidth != 0 && pos + mapWidth < size && !wallStitcheable.contains(map[pos + 1 + mapWidth])) + visual += 2; + if ((pos+1) % mapWidth != 0 && !wallStitcheable.contains(map[pos + 1])) + visual += 1; + return visual; + } + + } else if (Dungeon.level.insideMap(pos) && wallStitcheable.contains(map[pos+mapWidth])) { + + int visual; + if (map[pos] == Terrain.DOOR || map[pos] == Terrain.LOCKED_DOOR) + visual = DungeonTileSheet.DOOR_SIDEWAYS_OVERHANG; + else if (map[pos] == Terrain.OPEN_DOOR) + visual = DungeonTileSheet.DOOR_SIDEWAYS_OVERHANG_OPEN; + else + visual = DungeonTileSheet.WALL_OVERHANG; + + if (!wallStitcheable.contains(map[pos - 1 + mapWidth])) + visual += 2; + if (!wallStitcheable.contains(map[pos + 1 + mapWidth])) + visual += 1; + + return visual; + + } else if (Dungeon.level.insideMap(pos) && (map[pos+mapWidth] == Terrain.DOOR || map[pos+mapWidth] == Terrain.LOCKED_DOOR) ) { + return DungeonTileSheet.DOOR_OVERHANG; + } else if (Dungeon.level.insideMap(pos) && map[pos+mapWidth] == Terrain.OPEN_DOOR ) { + return DungeonTileSheet.DOOR_OVERHANG_OPEN; + } + + return -1; + } + + @Override + public boolean overlapsPoint( float x, float y ) { + return true; + } + + @Override + public boolean overlapsScreenPoint( int x, int y ) { + return true; + } + + @Override + protected boolean needsRender(int pos) { + return data[pos] != -1; + } +}