diff --git a/core/src/main/assets/tiles_sewer.png b/core/src/main/assets/tiles_sewer.png new file mode 100644 index 000000000..d2d995146 Binary files /dev/null and b/core/src/main/assets/tiles_sewer.png differ 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; + } +}