v0.4.3: separated tile display logic from tile types

also re-added visual only tile types
This commit is contained in:
Evan Debenham 2016-09-27 04:06:06 -04:00
parent 2a73678529
commit 2d52a66ac6
11 changed files with 168 additions and 52 deletions

View File

@ -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 ) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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() {

View File

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