v0.4.2: performance optimizations for blobs

This commit is contained in:
Evan Debenham 2016-09-06 00:12:29 -04:00
parent b25ccd8bb3
commit 60c16201cf
14 changed files with 227 additions and 189 deletions

View File

@ -48,6 +48,7 @@ public class Alchemy extends Blob {
@Override
protected void evolve() {
volume = off[pos] = cur[pos];
area.union(pos%Dungeon.level.width(), pos/Dungeon.level.width());
if (Dungeon.visible[pos]) {
Journal.add( Journal.Feature.ALCHEMY );
@ -56,12 +57,14 @@ public class Alchemy extends Blob {
@Override
public void seed( Level level, int cell, int amount ) {
if (cur == null) cur = new int[level.length()];
if (off == null) off = new int[cur.length];
super.seed(level, cell, amount);
cur[pos] = 0;
pos = cell;
volume = cur[pos] = amount;
area.setEmpty();
area.union(cell%level.width(), cell/level.width());
}
public static void transmute( int cell ) {

View File

@ -27,6 +27,7 @@ import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.utils.BArray;
import com.watabou.utils.Bundle;
import com.watabou.utils.Rect;
import java.util.Arrays;
@ -42,7 +43,9 @@ public class Blob extends Actor {
protected int[] off;
public BlobEmitter emitter;
public Rect area = new Rect();
private static final String CUR = "cur";
private static final String START = "start";
private static final String LENGTH = "length";
@ -110,17 +113,30 @@ public class Blob extends Actor {
if (volume > 0) {
if (area.isEmpty())
setupArea();
volume = 0;
evolve();
int[] tmp = off;
off = cur;
cur = tmp;
} else {
area.setEmpty();
}
return true;
}
public void setupArea(){
for (int cell=0; cell < cur.length; cell++) {
if (cur[cell] != 0){
area.union(cell%Dungeon.level.width(), cell/Dungeon.level.width());
}
}
}
public void use( BlobEmitter emitter ) {
this.emitter = emitter;
@ -128,42 +144,50 @@ public class Blob extends Actor {
protected void evolve() {
boolean[] notBlocking = BArray.not( Level.solid, null );
for (int i=1; i < Dungeon.level.height()-1; i++) {
int from = i * Dungeon.level.width() + 1;
int to = from + Dungeon.level.width() - 2;
for (int pos=from; pos < to; pos++) {
if (notBlocking[pos]) {
boolean[] blocking = Level.solid;
int cell;
for (int i=area.top-1; i <= area.bottom; i++) {
for (int j = area.left-1; j <= area.right; j++) {
cell = j + i*Dungeon.level.width();
if (!blocking[cell]) {
int count = 1;
int sum = cur[pos];
int sum = cur[cell];
if (notBlocking[pos-1]) {
sum += cur[pos-1];
if (!blocking[cell-1]) {
sum += cur[cell-1];
count++;
}
if (notBlocking[pos+1]) {
sum += cur[pos+1];
if (!blocking[cell+1]) {
sum += cur[cell+1];
count++;
}
if (notBlocking[pos-Dungeon.level.width()]) {
sum += cur[pos-Dungeon.level.width()];
if (!blocking[cell-Dungeon.level.width()]) {
sum += cur[cell-Dungeon.level.width()];
count++;
}
if (notBlocking[pos+Dungeon.level.width()]) {
sum += cur[pos+Dungeon.level.width()];
if (!blocking[cell+Dungeon.level.width()]) {
sum += cur[cell+Dungeon.level.width()];
count++;
}
int value = sum >= count ? (sum / count) - 1 : 0;
off[pos] = value;
off[cell] = value;
if (value > 0){
if (i < area.top)
area.top = i;
else if (i >= area.bottom)
area.bottom = i+1;
if (j < area.left)
area.left = j;
else if (j >= area.right)
area.right = j+1;
}
volume += value;
} else {
off[pos] = 0;
off[cell] = 0;
}
}
}
@ -175,6 +199,8 @@ public class Blob extends Actor {
cur[cell] += amount;
volume += amount;
area.union(cell%level.width(), cell/level.width());
}
public void clear( int cell ) {
@ -184,6 +210,7 @@ public class Blob extends Actor {
public void fullyClear(){
volume = 0;
area.setEmpty();
cur = new int[Dungeon.level.length()];
off = new int[Dungeon.level.length()];
}

View File

@ -36,10 +36,15 @@ public class ConfusionGas extends Blob {
super.evolve();
Char ch;
for (int i = 0; i < Dungeon.level.length(); i++) {
if (cur[i] > 0 && (ch = Actor.findChar( i )) != null) {
if (!ch.immunities().contains(this.getClass()))
Buff.prolong( ch, Vertigo.class, 2 );
int cell;
for (int i = area.left; i < area.right; i++){
for (int j = area.top; j < area.bottom; j++){
cell = i + j*Dungeon.level.width();
if (cur[cell] > 0 && (ch = Actor.findChar( cell )) != null) {
if (!ch.immunities().contains(this.getClass()))
Buff.prolong( ch, Vertigo.class, 2 );
}
}
}
}

View File

@ -39,52 +39,51 @@ public class Fire extends Blob {
protected void evolve() {
boolean[] flamable = Level.flamable;
int from = Dungeon.level.width() + 1;
int to = Dungeon.level.length() - Dungeon.level.width() - 1;
int cell;
int fire;
boolean observe = false;
for (int pos=from; pos < to; pos++) {
int fire;
if (cur[pos] > 0) {
burn( pos );
fire = cur[pos] - 1;
if (fire <= 0 && flamable[pos]) {
int oldTile = Dungeon.level.map[pos];
Dungeon.level.destroy( pos );
observe = true;
GameScene.updateMap( pos );
if (Dungeon.visible[pos]) {
GameScene.discoverTile( pos, oldTile );
for (int i = area.left-1; i <= area.right; i++) {
for (int j = area.top-1; j <= area.bottom; j++) {
cell = i + j*Dungeon.level.width();
if (cur[cell] > 0) {
burn( cell );
fire = cur[cell] - 1;
if (fire <= 0 && flamable[cell]) {
int oldTile = Dungeon.level.map[cell];
Dungeon.level.destroy( cell );
observe = true;
GameScene.updateMap( cell );
if (Dungeon.visible[cell]) {
GameScene.discoverTile( cell, oldTile );
}
}
}
} else {
if (flamable[pos]
&& (cur[pos-1] > 0
|| cur[pos+1] > 0
|| cur[pos-Dungeon.level.width()] > 0
|| cur[pos+Dungeon.level.width()] > 0)) {
fire = 4;
burn( pos );
} else {
fire = 0;
if (flamable[cell]
&& (cur[cell-1] > 0
|| cur[cell+1] > 0
|| cur[cell-Dungeon.level.width()] > 0
|| cur[cell+Dungeon.level.width()] > 0)) {
fire = 4;
burn( cell );
area.union(i, j);
} else {
fire = 0;
}
}
volume += (off[cell] = fire);
}
volume += (off[pos] = fire);
}
if (observe) {
Dungeon.observe();
}
@ -107,15 +106,6 @@ public class Fire extends Blob {
}
}
public void seed( Level level, int cell, int amount ) {
if (cur == null) cur = new int[level.length()];
if (off == null) off = new int[cur.length];
if (cur[cell] == 0) {
volume += amount;
cur[cell] = amount;
}
}
@Override
public void use( BlobEmitter emitter ) {
super.use( emitter );

View File

@ -37,29 +37,29 @@ public class Foliage extends Blob {
@Override
protected void evolve() {
int from = Dungeon.level.width() + 1;
int to = Dungeon.level.length() - Dungeon.level.width() - 1;
int[] map = Dungeon.level.map;
boolean regrowth = false;
boolean visible = false;
for (int pos=from; pos < to; pos++) {
if (cur[pos] > 0) {
off[pos] = cur[pos];
volume += off[pos];
if (map[pos] == Terrain.EMBERS) {
map[pos] = Terrain.GRASS;
regrowth = true;
int cell;
for (int i = area.left; i < area.right; i++) {
for (int j = area.top; j < area.bottom; j++) {
cell = i + j*Dungeon.level.width();
if (cur[cell] > 0) {
off[cell] = cur[cell];
volume += off[cell];
if (map[cell] == Terrain.EMBERS) {
map[cell] = Terrain.GRASS;
GameScene.updateMap(cell);
}
visible = visible || Dungeon.visible[cell];
} else {
off[cell] = 0;
}
visible = visible || Dungeon.visible[pos];
} else {
off[pos] = 0;
}
}
@ -67,11 +67,7 @@ public class Foliage extends Blob {
if (hero.isAlive() && hero.visibleEnemies() == 0 && cur[hero.pos] > 0) {
Buff.affect( hero, Shadows.class ).prolong();
}
if (regrowth) {
GameScene.updateMap();
}
if (visible) {
Journal.add( Journal.Feature.GARDEN );
}

View File

@ -41,27 +41,20 @@ public class GooWarn extends Blob {
@Override
protected void evolve() {
for (int i = 0; i < Dungeon.level.length(); i++) {
int offv = cur[i] > 0 ? cur[i] - 1 : 0;
off[i] = offv;
int cell;
if (offv > 0) {
volume += offv;
for (int i = area.left; i < area.right; i++){
for (int j = area.top; j < area.bottom; j++){
cell = i + j*Dungeon.level.width();
off[cell] = cur[cell] > 0 ? cur[cell] - 1 : 0;
if (off[cell] > 0) {
volume += off[cell];
}
}
}
}
public void seed(Level level, int cell, int amount ) {
if (cur == null) cur = new int[level.length()];
if (off == null) off = new int[cur.length];
int diff = amount - cur[cell];
if (diff > 0) {
cur[cell] = amount;
volume += diff;
}
}
@Override

View File

@ -36,10 +36,15 @@ public class ParalyticGas extends Blob {
super.evolve();
Char ch;
for (int i = 0; i < Dungeon.level.length(); i++) {
if (cur[i] > 0 && (ch = Actor.findChar( i )) != null) {
if (!ch.immunities().contains(this.getClass()))
Buff.prolong( ch, Paralysis.class, Paralysis.duration( ch ) );
int cell;
for (int i = area.left; i < area.right; i++) {
for (int j = area.top; j < area.bottom; j++) {
cell = i + j * Dungeon.level.width();
if (cur[cell] > 0 && (ch = Actor.findChar(cell)) != null) {
if (!ch.immunities().contains(this.getClass()))
Buff.prolong(ch, Paralysis.class, Paralysis.duration(ch));
}
}
}
}

View File

@ -38,33 +38,32 @@ public class Regrowth extends Blob {
super.evolve();
if (volume > 0) {
for (int i=0; i < Dungeon.level.length(); i++) {
if (off[i] > 0) {
int c = Dungeon.level.map[i];
int c1 = c;
if (c == Terrain.EMPTY || c == Terrain.EMBERS || c == Terrain.EMPTY_DECO) {
c1 = cur[i] > 9 ? Terrain.HIGH_GRASS : Terrain.GRASS;
} else if (c == Terrain.GRASS && cur[i] > 9 && Dungeon.level.plants.get(i) == null ) {
c1 = Terrain.HIGH_GRASS;
}
if (c1 != c) {
Level.set( i, Terrain.HIGH_GRASS );
Dungeon.observe();
GameScene.updateMap( i );
if (Dungeon.visible[i]) {
GameScene.discoverTile( i, c );
int cell;
for (int i = area.left; i < area.right; i++) {
for (int j = area.top; j < area.bottom; j++) {
cell = i + j*Dungeon.level.width();
if (off[cell] > 0) {
int c = Dungeon.level.map[cell];
int c1 = c;
if (c == Terrain.EMPTY || c == Terrain.EMBERS || c == Terrain.EMPTY_DECO) {
c1 = cur[cell] > 9 ? Terrain.HIGH_GRASS : Terrain.GRASS;
} else if (c == Terrain.GRASS && cur[cell] > 9 && Dungeon.level.plants.get(cell) == null ) {
c1 = Terrain.HIGH_GRASS;
}
if (c1 != c) {
Level.set( cell, c1 );
GameScene.updateMap( cell );
}
Char ch = Actor.findChar( cell );
if (ch != null && off[cell] > 1) {
Buff.prolong( ch, Roots.class, TICK );
}
}
Char ch = Actor.findChar( i );
if (ch != null && cur[i] > 1) {
Buff.prolong( ch, Roots.class, TICK );
}
}
}
Dungeon.observe();
}
}

View File

@ -25,6 +25,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Vertigo;
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
@ -36,10 +37,15 @@ public class StenchGas extends Blob {
super.evolve();
Char ch;
for (int i = 0; i < Dungeon.level.length(); i++) {
if (cur[i] > 0 && (ch = Actor.findChar(i)) != null) {
if (!ch.immunities().contains(this.getClass()))
Buff.prolong( ch, Paralysis.class, Paralysis.duration( ch )/5 );
int cell;
for (int i = area.left; i < area.right; i++){
for (int j = area.top; j < area.bottom; j++){
cell = i + j*Dungeon.level.width();
if (cur[cell] > 0 && (ch = Actor.findChar( cell )) != null) {
if (!ch.immunities().contains(this.getClass()))
Buff.prolong( ch, Paralysis.class, Paralysis.duration( ch )/5 );
}
}
}
}

View File

@ -40,15 +40,19 @@ public class ToxicGas extends Blob implements Hero.Doom {
int levelDamage = 5 + Dungeon.depth * 5;
Char ch;
for (int i=0; i < Dungeon.level.length(); i++) {
if (cur[i] > 0 && (ch = Actor.findChar( i )) != null) {
int cell;
int damage = (ch.HT + levelDamage) / 40;
if (Random.Int( 40 ) < (ch.HT + levelDamage) % 40) {
damage++;
for (int i = area.left; i < area.right; i++){
for (int j = area.top; j < area.bottom; j++){
cell = i + j*Dungeon.level.width();
if (cur[cell] > 0 && (ch = Actor.findChar( cell )) != null) {
int damage = (ch.HT + levelDamage) / 40;
if (Random.Int( 40 ) < (ch.HT + levelDamage) % 40) {
damage++;
}
ch.damage( damage, this );
}
ch.damage( damage, this );
}
}
}

View File

@ -42,10 +42,15 @@ public class VenomGas extends Blob {
strength = 0;
} else {
Char ch;
for (int i = 0; i < Dungeon.level.length(); i++) {
if (cur[i] > 0 && (ch = Actor.findChar(i)) != null) {
if (!ch.immunities().contains(this.getClass()))
Buff.affect(ch, Venom.class).set(2f, strength);
int cell;
for (int i = area.left; i < area.right; i++){
for (int j = area.top; j < area.bottom; j++){
cell = i + j*Dungeon.level.width();
if (cur[cell] > 0 && (ch = Actor.findChar( cell )) != null) {
if (!ch.immunities().contains(this.getClass()))
Buff.affect(ch, Venom.class).set(2f, strength);
}
}
}
}

View File

@ -24,6 +24,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Roots;
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.WebParticle;
@ -34,19 +35,22 @@ public class Web extends Blob {
@Override
protected void evolve() {
for (int i = 0; i < Dungeon.level.length(); i++) {
int offv = cur[i] > 0 ? cur[i] - 1 : 0;
off[i] = offv;
if (offv > 0) {
volume += offv;
Char ch = Actor.findChar( i );
if (ch != null) {
Buff.prolong( ch, Roots.class, TICK );
int cell;
for (int i = area.left; i < area.right; i++){
for (int j = area.top; j < area.bottom; j++){
cell = i + j*Dungeon.level.width();
off[cell] = cur[cell] > 0 ? cur[cell] - 1 : 0;
if (off[cell] > 0) {
volume += off[cell];
Char ch = Actor.findChar( cell );
if (ch != null) {
Buff.prolong( ch, Roots.class, TICK );
}
}
}
}
@ -59,16 +63,6 @@ public class Web extends Blob {
emitter.pour( WebParticle.FACTORY, 0.4f );
}
public void seed(Level level, int cell, int amount ) {
if (cur == null) cur = new int[level.length()];
if (off == null) off = new int[cur.length];
int diff = amount - cur[cell];
if (diff > 0) {
cur[cell] = amount;
volume += diff;
}
}
@Override
public String tileDesc() {
return Messages.get(this, "desc");

View File

@ -52,6 +52,7 @@ public class WellWater extends Blob {
@Override
protected void evolve() {
volume = off[pos] = cur[pos];
area.union(pos%Dungeon.level.width(), pos/Dungeon.level.width());
if (Dungeon.visible[pos]) {
if (this instanceof WaterOfAwareness) {
@ -125,11 +126,14 @@ public class WellWater extends Blob {
@Override
public void seed( Level level, int cell, int amount ) {
if (cur == null) cur = new int[level.length()];
if (off == null) off = new int[cur.length];
super.seed(level, cell, amount);
cur[pos] = 0;
pos = cell;
volume = cur[pos] = amount;
area.setEmpty();
area.union(cell%level.width(), cell/level.width());
}
public static void affectCell( int cell ) {

View File

@ -44,15 +44,22 @@ public class BlobEmitter extends Emitter {
if (blob.volume <= 0) {
return;
}
if (blob.area.isEmpty())
blob.setupArea();
int[] map = blob.cur;
float size = DungeonTilemap.SIZE;
for (int i=0; i < Dungeon.level.length(); i++) {
if (map[i] > 0 && Dungeon.visible[i]) {
float x = ((i % Dungeon.level.width()) + Random.Float()) * size;
float y = ((i / Dungeon.level.width()) + Random.Float()) * size;
factory.emit( this, index, x, y );
int cell;
for (int i = blob.area.left; i < blob.area.right; i++) {
for (int j = blob.area.top; j < blob.area.bottom; j++) {
cell = i + j*Dungeon.level.width();
if (map[cell] > 0 && Dungeon.visible[cell]) {
float x = (i + Random.Float()) * size;
float y = (j + Random.Float()) * size;
factory.emit(this, index, x, y);
}
}
}
}