diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java index 3b4bea439..de6b17516 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java @@ -663,8 +663,7 @@ public class Dungeon { return; } - level.updateFieldOfView( hero ); - System.arraycopy( Level.fieldOfView, 0, visible, 0, visible.length ); + level.updateFieldOfView(hero, visible); BArray.or( level.visited, visible, level.visited ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java index ba6f3e573..72328e620 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java @@ -79,7 +79,7 @@ public abstract class Char extends Actor { @Override protected boolean act() { - Dungeon.level.updateFieldOfView( this ); + Dungeon.level.updateFieldOfView( this, Level.fieldOfView ); return false; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Guard.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Guard.java index 4cadcb25f..cba4a508d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Guard.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Guard.java @@ -65,7 +65,7 @@ public class Guard extends Mob { @Override protected boolean act() { - Dungeon.level.updateFieldOfView( this ); + Dungeon.level.updateFieldOfView( this, Level.fieldOfView ); if (state == HUNTING && paralysed <= 0 && diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Piranha.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Piranha.java index 04119b999..0666ccc66 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Piranha.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Piranha.java @@ -62,7 +62,7 @@ public class Piranha extends Mob { return true; } else { //this causes pirahna to move away when a door is closed on them. - Dungeon.level.updateFieldOfView( this ); + Dungeon.level.updateFieldOfView( this, Level.fieldOfView ); enemy = chooseEnemy(); if (state == this.HUNTING && !(enemy != null && enemy.isAlive() && Level.fieldOfView[enemy.pos] && enemy.invisible <= 0)){ 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 aa78868fb..484ad862d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java @@ -74,6 +74,7 @@ import com.shatteredpixel.shatteredpixeldungeon.plants.Plant; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite; import com.shatteredpixel.shatteredpixeldungeon.ui.CustomTileVisual; +import com.shatteredpixel.shatteredpixeldungeon.utils.BArray; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; import com.watabou.noosa.Game; import com.watabou.noosa.Group; @@ -544,6 +545,8 @@ public abstract class Level implements Bundlable { protected void buildFlagMaps() { + fieldOfView = new boolean[length()]; + passable = new boolean[length()]; losBlocking = new boolean[length()]; flamable = new boolean[length()]; @@ -896,10 +899,8 @@ public abstract class Level implements Bundlable { } } - public boolean[] updateFieldOfView( Char c ) { + public void updateFieldOfView( Char c, boolean[] fieldOfView ) { - fieldOfView = new boolean[length()]; - int cx = c.pos % width(); int cy = c.pos / width(); @@ -907,10 +908,13 @@ public abstract class Level implements Bundlable { && c.buff( TimekeepersHourglass.timeStasis.class ) == null && c.isAlive(); if (sighted) { ShadowCaster.castShadow( cx, cy, fieldOfView, c.viewDistance ); + } else { + BArray.setFalse(fieldOfView); } int sense = 1; - if (c.isAlive()) { + //Currently only the hero can get mind vision + if (c.isAlive() && c == Dungeon.hero) { for (Buff b : c.buffs( MindVision.class )) { sense = Math.max( ((MindVision)b).distance, sense ); } @@ -926,15 +930,12 @@ public abstract class Level implements Bundlable { int len = bx - ax + 1; int pos = ax + ay * width(); for (int y = ay; y <= by; y++, pos+=width()) { - Arrays.fill( fieldOfView, pos, pos + len, true ); - } - - for (int i=0; i < length(); i++) { - fieldOfView[i] &= discoverable[i]; + System.arraycopy(discoverable, pos, fieldOfView, pos, len); } } - - if (c.isAlive()) { + + //Currently only the hero can get mind vision or awareness + if (c.isAlive() && c == Dungeon.hero) { if (c.buff( MindVision.class ) != null) { for (Mob mob : mobs) { int p = mob.pos; @@ -948,7 +949,7 @@ public abstract class Level implements Bundlable { fieldOfView[p + width()] = true; fieldOfView[p - width()] = true; } - } else if (c == Dungeon.hero && ((Hero)c).heroClass == HeroClass.HUNTRESS) { + } else if (((Hero)c).heroClass == HeroClass.HUNTRESS) { for (Mob mob : mobs) { int p = mob.pos; if (distance( c.pos, p) == 2) { @@ -980,11 +981,12 @@ public abstract class Level implements Bundlable { } } - for (Heap heap : heaps.values()) - if (!heap.seen && fieldOfView[heap.pos] && c == Dungeon.hero) - heap.seen = true; - - return fieldOfView; + if (c == Dungeon.hero) { + for (Heap heap : heaps.values()) + if (!heap.seen && fieldOfView[heap.pos]) + heap.seen = true; + } + } public int distance( int a, int b ) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/mechanics/ShadowCaster.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/mechanics/ShadowCaster.java index fc6a7b7a6..68c0858b0 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/mechanics/ShadowCaster.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/mechanics/ShadowCaster.java @@ -22,18 +22,13 @@ package com.shatteredpixel.shatteredpixeldungeon.mechanics; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; - -import java.util.Arrays; +import com.shatteredpixel.shatteredpixeldungeon.utils.BArray; public final class ShadowCaster { private static final int MAX_DISTANCE = 8; - - private static int distance; - private static int limits[]; - - private static boolean[] losBlocking; - private static boolean[] fieldOfView; + + private static boolean[] falseArray; private static int[][] rounding; static { @@ -46,30 +41,28 @@ public final class ShadowCaster { } } - private static Obstacles obs = new Obstacles(); - public static void castShadow( int x, int y, boolean[] fieldOfView, int distance ) { - losBlocking = Level.losBlocking; - - ShadowCaster.distance = distance; - limits = rounding[distance]; - - ShadowCaster.fieldOfView = fieldOfView; - Arrays.fill( fieldOfView, false ); + BArray.setFalse(fieldOfView); + fieldOfView[y * Dungeon.level.width() + x] = true; - - scanSector( x, y, +1, +1, 0, 0 ); - scanSector( x, y, -1, +1, 0, 0 ); - scanSector( x, y, +1, -1, 0, 0 ); - scanSector( x, y, -1, -1, 0, 0 ); - scanSector( x, y, 0, 0, +1, +1 ); - scanSector( x, y, 0, 0, -1, +1 ); - scanSector( x, y, 0, 0, +1, -1 ); - scanSector( x, y, 0, 0, -1, -1 ); + + boolean[] losBlocking = Level.losBlocking; + Obstacles obs = new Obstacles(); + + scanSector( distance, fieldOfView, losBlocking, obs, x, y, +1, +1, 0, 0 ); + scanSector( distance, fieldOfView, losBlocking, obs, x, y, -1, +1, 0, 0 ); + scanSector( distance, fieldOfView, losBlocking, obs, x, y, +1, -1, 0, 0 ); + scanSector( distance, fieldOfView, losBlocking, obs, x, y, -1, -1, 0, 0 ); + scanSector( distance, fieldOfView, losBlocking, obs, x, y, 0, 0, +1, +1 ); + scanSector( distance, fieldOfView, losBlocking, obs, x, y, 0, 0, -1, +1 ); + scanSector( distance, fieldOfView, losBlocking, obs, x, y, 0, 0, +1, -1 ); + scanSector( distance, fieldOfView, losBlocking, obs, x, y, 0, 0, -1, -1 ); + } - - private static void scanSector( int cx, int cy, int m1, int m2, int m3, int m4 ) { + + //TODO: This is still fairly expensive, look into further optimizing this + private static void scanSector( int distance, boolean[] fieldOfView, boolean[] losBlocking, Obstacles obs, int cx, int cy, int m1, int m2, int m3, int m4 ) { obs.reset(); @@ -77,7 +70,7 @@ public final class ShadowCaster { float dq2 = 0.5f / p; - int pp = limits[p]; + int pp = rounding[distance][p]; for (int q=0; q <= pp; q++) { int x = cx + q * m1 + p * m3; @@ -112,8 +105,8 @@ public final class ShadowCaster { private static final class Obstacles { private static int SIZE = (MAX_DISTANCE+1) * (MAX_DISTANCE+1) / 2; - private static float[] a1 = new float[SIZE]; - private static float[] a2 = new float[SIZE]; + private float[] a1 = new float[SIZE]; + private float[] a2 = new float[SIZE]; private int length; private int limit; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/utils/BArray.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/utils/BArray.java index 1c3b7c39f..5dec9a88a 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/utils/BArray.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/utils/BArray.java @@ -22,6 +22,16 @@ package com.shatteredpixel.shatteredpixeldungeon.utils; public class BArray { + private static boolean[] falseArray; + + //This is MUCH faster than making a new boolean[] or using Arrays.fill; + public static void setFalse( boolean[] toBeFalse ){ + if (falseArray == null || falseArray.length < toBeFalse.length) + falseArray = new boolean[toBeFalse.length]; + + System.arraycopy(falseArray, 0, toBeFalse, 0, toBeFalse.length); + } + public static boolean[] and( boolean[] a, boolean[] b, boolean[] result ) { int length = a.length;