diff --git a/SPD-classes/src/main/java/com/watabou/utils/PathFinder.java b/SPD-classes/src/main/java/com/watabou/utils/PathFinder.java index a4eeb0387..7b91cb70a 100644 --- a/SPD-classes/src/main/java/com/watabou/utils/PathFinder.java +++ b/SPD-classes/src/main/java/com/watabou/utils/PathFinder.java @@ -42,9 +42,10 @@ public class PathFinder { public static int[] NEIGHBOURS8; public static int[] NEIGHBOURS9; - //similar to NEIGHBOURS8, but the order is circular. + //similar to their equivalent neighbour arrays, but the order is clockwise. //Useful for some logic functions, but is slower due to lack of array-access order. - public static int[] CIRCLE; + public static int[] CIRCLE4; + public static int[] CIRCLE8; public static void setMapSize( int width, int height ) { @@ -64,7 +65,8 @@ public class PathFinder { NEIGHBOURS8 = new int[]{-width-1, -width, -width+1, -1, +1, +width-1, +width, +width+1}; NEIGHBOURS9 = new int[]{-width-1, -width, -width+1, -1, 0, +1, +width-1, +width, +width+1}; - CIRCLE = new int[]{-width-1, -width, -width+1, +1, +width+1, +width, +width-1, -1}; + CIRCLE4 = new int[]{-width, +1, +width, -1}; + CIRCLE8 = new int[]{-width-1, -width, -width+1, +1, +width+1, +width, +width-1, -1}; } public static Path find( int from, int to, boolean[] passable ) { diff --git a/core/src/main/assets/tiles0.png b/core/src/main/assets/tiles0.png index 9243413f2..f32632a0a 100644 Binary files a/core/src/main/assets/tiles0.png and b/core/src/main/assets/tiles0.png differ diff --git a/core/src/main/assets/tiles1.png b/core/src/main/assets/tiles1.png index 78640c4de..91b6a4c07 100644 Binary files a/core/src/main/assets/tiles1.png and b/core/src/main/assets/tiles1.png differ diff --git a/core/src/main/assets/tiles2.png b/core/src/main/assets/tiles2.png index d3ec82dea..fa1adbc6a 100644 Binary files a/core/src/main/assets/tiles2.png and b/core/src/main/assets/tiles2.png differ diff --git a/core/src/main/assets/tiles3.png b/core/src/main/assets/tiles3.png index c5af2d100..445f5363c 100644 Binary files a/core/src/main/assets/tiles3.png and b/core/src/main/assets/tiles3.png differ diff --git a/core/src/main/assets/tiles4.png b/core/src/main/assets/tiles4.png index c6c3096cc..22177651c 100644 Binary files a/core/src/main/assets/tiles4.png and b/core/src/main/assets/tiles4.png differ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/DungeonTilemap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/DungeonTilemap.java index 0f3f5a8c9..ee6fe881d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/DungeonTilemap.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/DungeonTilemap.java @@ -20,21 +20,105 @@ */ package com.shatteredpixel.shatteredpixeldungeon; +import android.util.SparseIntArray; + import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.watabou.noosa.Image; import com.watabou.noosa.TextureFilm; import com.watabou.noosa.Tilemap; import com.watabou.noosa.tweeners.AlphaTweener; +import com.watabou.utils.PathFinder; import com.watabou.utils.Point; import com.watabou.utils.PointF; +import java.util.Arrays; +import java.util.List; + public class DungeonTilemap extends Tilemap { public static final int SIZE = 16; private static DungeonTilemap instance; - + + //Used to map dungeon tiles to their default visual values + public static SparseIntArray defaultVisuals = new SparseIntArray(32); + static { + defaultVisuals = new SparseIntArray(32); + 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.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.WATER, 63); + } + + //These tiles can stitch with water + public static List waterStitcheable = Arrays.asList( + Terrain.EMPTY, Terrain.GRASS, Terrain.EMPTY_WELL, + 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 + ); + + //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 ); + + //special floor + chasmStitcheable.put( Terrain.EMPTY_SP, 33 ); + chasmStitcheable.put( Terrain.STATUE_SP, 33 ); + + //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 ); + + //water + chasmStitcheable.put( Terrain.WATER, 35 ); + } + + private int[] map; + public DungeonTilemap() { super( Dungeon.level.tilesTex(), @@ -43,8 +127,48 @@ public class DungeonTilemap extends Tilemap { instance = this; } - - public int screenToTile( int x, int y ) { + + @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] = setCellVisuals(i ,map[i]); + } + + @Override + public synchronized void updateMapCell(int cell) { + //update in a 3x3 grid to accound for neighbours which might also be affected + super.updateMapCell(cell - mapWidth - 1); + super.updateMapCell(cell + mapWidth + 1); + for (int i : PathFinder.NEIGHBOURS9) + data[cell+i] = setCellVisuals(cell+i, map[cell+i]); + } + + private int setCellVisuals(int pos, int tile){ + if (tile == Terrain.WATER){ + tile = defaultVisuals.get(tile); + for (int i = 0; i < PathFinder.CIRCLE4.length; i++){ + if (waterStitcheable.contains(map[pos + PathFinder.CIRCLE4[i]])) { + //equivalent to: cell -= 2^i + tile -= (1 << i); + } + } + return tile; + } else if (tile == Terrain.CHASM && pos >= mapWidth){ + return chasmStitcheable.get(map[pos - mapWidth], defaultVisuals.get(tile)); + } + return defaultVisuals.get(tile); + } + + public int screenToTile(int x, int y ) { Point p = camera().screenToCamera( x, y ). offset( this.point().negate() ). invScale( SIZE ). @@ -67,9 +191,6 @@ public class DungeonTilemap extends Tilemap { final Image tile = tile( oldValue ); tile.point( tileToWorld( pos ) ); - // For bright mode - tile.rm = tile.gm = tile.bm = rm; - tile.ra = tile.ga = tile.ba = ra; parent.add( tile ); parent.add( new AlphaTweener( tile, 0, 0.6f ) { @@ -92,7 +213,7 @@ public class DungeonTilemap extends Tilemap { public static Image tile( int index ) { Image img = new Image( instance.texture ); - img.frame( instance.tileset.get( index ) ); + img.frame( instance.tileset.get( defaultVisuals.get(index) ) ); return img; } @@ -103,6 +224,7 @@ public class DungeonTilemap extends Tilemap { @Override protected boolean needsRender(int pos) { - return (Level.discoverable[pos] || Dungeon.level.map[pos] == Terrain.CHASM) && Dungeon.level.map[pos] != Terrain.WATER; + return (Level.discoverable[pos] || data[pos] == defaultVisuals.get(Terrain.CHASM)) + && data[pos] != defaultVisuals.get(Terrain.WATER); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfFireblast.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfFireblast.java index 02945833f..68eeedcb9 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfFireblast.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfFireblast.java @@ -100,9 +100,9 @@ public class WandOfFireblast extends DamageWand { affectedCells.add(cell); if (strength >= 1.5f) { visualCells.remove(cell); - spreadFlames(cell + PathFinder.CIRCLE[left(direction)], strength - 1.5f); - spreadFlames(cell + PathFinder.CIRCLE[direction], strength - 1.5f); - spreadFlames(cell + PathFinder.CIRCLE[right(direction)], strength - 1.5f); + spreadFlames(cell + PathFinder.CIRCLE8[left(direction)], strength - 1.5f); + spreadFlames(cell + PathFinder.CIRCLE8[direction], strength - 1.5f); + spreadFlames(cell + PathFinder.CIRCLE8[right(direction)], strength - 1.5f); } else { visualCells.add(cell); } @@ -134,8 +134,8 @@ public class WandOfFireblast extends DamageWand { int maxDist = (int)(4 * Math.pow(1.5,(chargesPerCast()-1))); int dist = Math.min(bolt.dist, maxDist); - for (int i = 0; i < PathFinder.CIRCLE.length; i++){ - if (bolt.sourcePos+PathFinder.CIRCLE[i] == bolt.path.get(1)){ + for (int i = 0; i < PathFinder.CIRCLE8.length; i++){ + if (bolt.sourcePos+PathFinder.CIRCLE8[i] == bolt.path.get(1)){ direction = i; break; } @@ -146,9 +146,9 @@ public class WandOfFireblast extends DamageWand { strength--; //as we start at dist 1, not 0. affectedCells.add(c); if (strength > 1) { - spreadFlames(c + PathFinder.CIRCLE[left(direction)], strength - 1); - spreadFlames(c + PathFinder.CIRCLE[direction], strength - 1); - spreadFlames(c + PathFinder.CIRCLE[right(direction)], strength - 1); + spreadFlames(c + PathFinder.CIRCLE8[left(direction)], strength - 1); + spreadFlames(c + PathFinder.CIRCLE8[direction], strength - 1); + spreadFlames(c + PathFinder.CIRCLE8[right(direction)], strength - 1); } else { visualCells.add(c); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfRegrowth.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfRegrowth.java index dbe80de92..de126eb38 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfRegrowth.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfRegrowth.java @@ -111,9 +111,9 @@ public class WandOfRegrowth extends Wand { if (strength >= 0 && Level.passable[cell] && !Level.losBlocking[cell]){ affectedCells.add(cell); if (strength >= 1.5f) { - spreadRegrowth(cell + PathFinder.CIRCLE[left(direction)], strength - 1.5f); - spreadRegrowth(cell + PathFinder.CIRCLE[direction], strength - 1.5f); - spreadRegrowth(cell + PathFinder.CIRCLE[right(direction)], strength-1.5f); + spreadRegrowth(cell + PathFinder.CIRCLE8[left(direction)], strength - 1.5f); + spreadRegrowth(cell + PathFinder.CIRCLE8[direction], strength - 1.5f); + spreadRegrowth(cell + PathFinder.CIRCLE8[right(direction)], strength-1.5f); } else { visualCells.add(cell); } @@ -188,8 +188,8 @@ public class WandOfRegrowth extends Wand { int maxDist = Math.round(1.2f + chargesPerCast()*.8f); int dist = Math.min(bolt.dist, maxDist); - for (int i = 0; i < PathFinder.CIRCLE.length; i++){ - if (bolt.sourcePos+PathFinder.CIRCLE[i] == bolt.path.get(1)){ + for (int i = 0; i < PathFinder.CIRCLE8.length; i++){ + if (bolt.sourcePos+PathFinder.CIRCLE8[i] == bolt.path.get(1)){ direction = i; break; } @@ -200,9 +200,9 @@ public class WandOfRegrowth extends Wand { strength--; //as we start at dist 1, not 0. if (!Level.losBlocking[c]) { affectedCells.add(c); - spreadRegrowth(c + PathFinder.CIRCLE[left(direction)], strength - 1); - spreadRegrowth(c + PathFinder.CIRCLE[direction], strength - 1); - spreadRegrowth(c + PathFinder.CIRCLE[right(direction)], strength - 1); + spreadRegrowth(c + PathFinder.CIRCLE8[left(direction)], strength - 1); + spreadRegrowth(c + PathFinder.CIRCLE8[direction], strength - 1); + spreadRegrowth(c + PathFinder.CIRCLE8[right(direction)], strength - 1); } else { visualCells.add(c); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java index ca48fcf82..8ad80672e 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java @@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Challenges; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.DungeonTilemap; import com.shatteredpixel.shatteredpixeldungeon.Statistics; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; @@ -595,24 +596,17 @@ public abstract class Level implements Bundlable { } public void destroy( int pos ) { - if ((Terrain.flags[map[pos]] & Terrain.UNSTITCHABLE) == 0) { - set( pos, Terrain.EMBERS ); - - } else { - boolean flood = false; + if (!DungeonTilemap.waterStitcheable.contains(map[pos])) { for (int j = 0; j < PathFinder.NEIGHBOURS4.length; j++) { if (water[pos + PathFinder.NEIGHBOURS4[j]]) { - flood = true; - break; + set(pos, Terrain.WATER); + return; } } - if (flood) { - set( pos, Terrain.WATER ); - } else { - set( pos, Terrain.EMBERS ); - } } + + set( pos, Terrain.EMBERS ); } protected void cleanWalls() { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Terrain.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Terrain.java index 1242389ba..567e97ab9 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Terrain.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Terrain.java @@ -76,29 +76,27 @@ public class Terrain { public static final int LIQUID = 0x40; public static final int PIT = 0x80; - public static final int UNSTITCHABLE = 0x100; - public static final int[] flags = new int[256]; static { - flags[CHASM] = AVOID | PIT | UNSTITCHABLE; + flags[CHASM] = AVOID | PIT; flags[EMPTY] = PASSABLE; flags[GRASS] = PASSABLE | FLAMABLE; flags[EMPTY_WELL] = PASSABLE; - flags[WATER] = PASSABLE | LIQUID | UNSTITCHABLE; - flags[WALL] = LOS_BLOCKING | SOLID | UNSTITCHABLE; - flags[DOOR] = PASSABLE | LOS_BLOCKING | FLAMABLE | SOLID | UNSTITCHABLE; - flags[OPEN_DOOR] = PASSABLE | FLAMABLE | UNSTITCHABLE; + flags[WATER] = PASSABLE | LIQUID; + flags[WALL] = LOS_BLOCKING | SOLID; + flags[DOOR] = PASSABLE | LOS_BLOCKING | FLAMABLE | SOLID; + flags[OPEN_DOOR] = PASSABLE | FLAMABLE; flags[ENTRANCE] = PASSABLE/* | SOLID*/; flags[EXIT] = PASSABLE; flags[EMBERS] = PASSABLE; - flags[LOCKED_DOOR] = LOS_BLOCKING | SOLID | UNSTITCHABLE; - flags[PEDESTAL] = PASSABLE | UNSTITCHABLE; + flags[LOCKED_DOOR] = LOS_BLOCKING | SOLID; + flags[PEDESTAL] = PASSABLE; flags[WALL_DECO] = flags[WALL]; flags[BARRICADE] = FLAMABLE | SOLID | LOS_BLOCKING; - flags[EMPTY_SP] = flags[EMPTY] | UNSTITCHABLE; + flags[EMPTY_SP] = flags[EMPTY]; flags[HIGH_GRASS] = PASSABLE | LOS_BLOCKING | FLAMABLE; - flags[SECRET_DOOR] = flags[WALL] | SECRET | UNSTITCHABLE; + flags[SECRET_DOOR] = flags[WALL] | SECRET; flags[SECRET_TRAP] = flags[EMPTY] | SECRET; flags[TRAP] = AVOID; flags[INACTIVE_TRAP]= flags[EMPTY]; @@ -109,8 +107,8 @@ public class Terrain { flags[SIGN] = PASSABLE | FLAMABLE; flags[WELL] = AVOID; flags[STATUE] = SOLID; - flags[STATUE_SP] = flags[STATUE] | UNSTITCHABLE; - flags[BOOKSHELF] = flags[BARRICADE] | UNSTITCHABLE; + flags[STATUE_SP] = flags[STATUE]; + flags[BOOKSHELF] = flags[BARRICADE]; flags[ALCHEMY] = PASSABLE; };