v0.4.2: FOV and shadowcaster optimizations
This commit is contained in:
parent
9f8981db07
commit
f1164af058
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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)){
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user