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;
+ }
+}