v0.4.3: separated tile display logic from tile types
also re-added visual only tile types
|
@ -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 ) {
|
||||
|
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
|