diff --git a/core/src/main/assets/plants.png b/core/src/main/assets/plants.png deleted file mode 100644 index 3ca895faa..000000000 Binary files a/core/src/main/assets/plants.png and /dev/null differ diff --git a/core/src/main/assets/terrain_features.png b/core/src/main/assets/terrain_features.png new file mode 100644 index 000000000..a70872c7a Binary files /dev/null and b/core/src/main/assets/terrain_features.png differ diff --git a/core/src/main/assets/traps.png b/core/src/main/assets/traps.png deleted file mode 100644 index 3cfda1376..000000000 Binary files a/core/src/main/assets/traps.png and /dev/null differ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java index 79dcae763..9ad977ae9 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java @@ -97,9 +97,8 @@ public class Assets { public static final String ROT_HEART= "rot_heart.png"; public static final String GUARD = "guard.png"; - public static final String ITEMS = "items.png"; - public static final String PLANTS = "plants.png"; - public static final String TRAPS = "traps.png"; + public static final String ITEMS = "items.png"; + public static final String TERRAIN_FEATURES = "terrain_features.png"; public static final String TILES_SEWERS = "tiles0.png"; public static final String TILES_PRISON = "tiles1.png"; 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 5aacac451..0287bb614 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java @@ -734,19 +734,19 @@ public abstract class Level implements Bundlable { map[pos] == Terrain.EMPTY_DECO) { map[pos] = Terrain.GRASS; flamable[pos] = true; - GameScene.updateMap( pos ); } plant = seed.couch( pos ); plants.put( pos, plant ); - GameScene.add( plant ); + GameScene.updateMap( pos ); return plant; } public void uproot( int pos ) { plants.remove(pos); + GameScene.updateMap( pos ); } public Trap setTrap( Trap trap, int pos ){ @@ -757,7 +757,7 @@ public abstract class Level implements Bundlable { } trap.set( pos ); traps.put( pos, trap ); - GameScene.add(trap); + GameScene.updateMap( pos ); return trap; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/PrisonBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/PrisonBossLevel.java index b632ef82a..dacab602f 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/PrisonBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/PrisonBossLevel.java @@ -216,9 +216,6 @@ public class PrisonBossLevel extends Level { } private void resetTraps(){ - for (Trap trap : traps.values()){ - trap.sprite.kill(); - } traps.clear(); for (int i = 0; i < length(); i++){ @@ -273,7 +270,6 @@ public class PrisonBossLevel extends Level { for (Plant plant : plants.values()){ if (safeArea == null || !safeArea.inside(cellToPoint(plant.pos))){ plants.remove(plant.pos); - plant.sprite.kill(); } } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/Trap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/Trap.java index 8eb923a5d..1c6a51903 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/Trap.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/Trap.java @@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.traps; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.sprites.TrapSprite; import com.watabou.noosa.audio.Sample; import com.watabou.noosa.tweeners.AlphaTweener; @@ -54,6 +55,7 @@ public abstract class Trap implements Bundlable { sprite.alpha( 0 ); sprite.parent.add( new AlphaTweener( sprite, 1, 0.6f)); } + GameScene.updateMap(pos); return this; } @@ -61,6 +63,7 @@ public abstract class Trap implements Bundlable { visible = false; if (sprite != null) sprite.visible = false; + GameScene.updateMap(pos); return this; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/plants/Plant.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/plants/Plant.java index 5d7b51d36..0d5cb2738 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/plants/Plant.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/plants/Plant.java @@ -38,7 +38,6 @@ import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.SandalsOfNature; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; -import com.shatteredpixel.shatteredpixeldungeon.sprites.PlantSprite; import com.watabou.noosa.audio.Sample; import com.watabou.utils.Bundlable; import com.watabou.utils.Bundle; @@ -52,8 +51,6 @@ public abstract class Plant implements Bundlable { public int image; public int pos; - - public PlantSprite sprite; public void trigger(){ @@ -71,8 +68,7 @@ public abstract class Plant implements Bundlable { public void wither() { Dungeon.level.uproot( pos ); - - sprite.kill(); + if (Dungeon.visible[pos]) { CellEmitter.get( pos ).burst( LeafParticle.GENERAL, 6 ); } @@ -142,7 +138,7 @@ public abstract class Plant implements Bundlable { @Override protected void onThrow( int cell ) { - if (Dungeon.level.map[cell] == Terrain.ALCHEMY || Level.pit[cell]) { + if (Dungeon.level.map[cell] == Terrain.ALCHEMY || Level.pit[cell] || Dungeon.level.traps.get(cell) != null) { super.onThrow( cell ); } else { Dungeon.level.plant( this, cell ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java index fb0dbf519..727cc5bb8 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java @@ -71,6 +71,7 @@ import com.shatteredpixel.shatteredpixeldungeon.ui.LootIndicator; import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton; import com.shatteredpixel.shatteredpixeldungeon.ui.ResumeIndicator; import com.shatteredpixel.shatteredpixeldungeon.ui.StatusPane; +import com.shatteredpixel.shatteredpixeldungeon.ui.TerrainFeaturesTilemap; import com.shatteredpixel.shatteredpixeldungeon.ui.Toast; import com.shatteredpixel.shatteredpixeldungeon.ui.Toolbar; import com.shatteredpixel.shatteredpixeldungeon.ui.Window; @@ -111,6 +112,7 @@ public class GameScene extends PixelScene { private SkinnedBlock water; private DungeonTilemap tiles; + private TerrainFeaturesTilemap terrainFeatures; private FogOfWar fog; private HeroSprite hero; @@ -193,30 +195,17 @@ public class GameScene extends PixelScene { for( CustomTileVisual visual : Dungeon.level.customTiles){ addCustomTile(visual.create()); } + + terrainFeatures = new TerrainFeaturesTilemap(Dungeon.level.plants, Dungeon.level.traps); + terrain.add(terrainFeatures); levelVisuals = Dungeon.level.addVisuals(); add(levelVisuals); - - traps = new Group(); - add(traps); - - int size = Dungeon.level.traps.size(); - for (int i=0; i < size; i++) { - addTrapSprite( Dungeon.level.traps.valueAt( i ) ); - } - - plants = new Group(); - add( plants ); - - size = Dungeon.level.plants.size(); - for (int i=0; i < size; i++) { - addPlantSprite( Dungeon.level.plants.valueAt( i ) ); - } heaps = new Group(); add( heaps ); - size = Dungeon.level.heaps.size(); + int size = Dungeon.level.heaps.size(); for (int i=0; i < size; i++) { addHeapSprite( Dungeon.level.heaps.valueAt( i ) ); } @@ -541,12 +530,11 @@ public class GameScene extends PixelScene { } private void addPlantSprite( Plant plant ) { - (plant.sprite = (PlantSprite)plants.recycle( PlantSprite.class )).reset( plant ); + } private void addTrapSprite( Trap trap ) { - (trap.sprite = (TrapSprite)traps.recycle( TrapSprite.class )).reset( trap ); - trap.sprite.visible = trap.visible; + } private void addBlobSprite( final Blob gas ) { @@ -689,12 +677,14 @@ public class GameScene extends PixelScene { public static void updateMap() { if (scene != null) { scene.tiles.updateMap(); + scene.terrainFeatures.updateMap(); } } public static void updateMap( int cell ) { if (scene != null) { scene.tiles.updateMapCell( cell ); + scene.terrainFeatures.updateMapCell( cell ); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/PlantSprite.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/PlantSprite.java index 1128f0b8c..a05e17ed7 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/PlantSprite.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/PlantSprite.java @@ -44,7 +44,7 @@ public class PlantSprite extends Image { private int pos = -1; public PlantSprite() { - super( Assets.PLANTS ); + super( Assets.TERRAIN_FEATURES ); if (frames == null) { frames = new TextureFilm( texture, 16, 16 ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/TrapSprite.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/TrapSprite.java index 72295d197..c9086b333 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/TrapSprite.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/TrapSprite.java @@ -56,7 +56,7 @@ public class TrapSprite extends Image { public TrapSprite() { - super( Assets.TRAPS ); + super( Assets.TERRAIN_FEATURES ); if (frames == null) { frames = new TextureFilm( texture, 16, 16 ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TerrainFeaturesTilemap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TerrainFeaturesTilemap.java new file mode 100644 index 000000000..ca359c06f --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TerrainFeaturesTilemap.java @@ -0,0 +1,140 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2016 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ +package com.shatteredpixel.shatteredpixeldungeon.ui; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; +import com.shatteredpixel.shatteredpixeldungeon.levels.traps.Trap; +import com.shatteredpixel.shatteredpixeldungeon.plants.Plant; +import com.shatteredpixel.shatteredpixeldungeon.sprites.TrapSprite; +import com.watabou.noosa.Image; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.Tilemap; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; +import com.watabou.utils.SparseArray; + +public class TerrainFeaturesTilemap extends Tilemap { + + public static final int SIZE = 16; + + private static TerrainFeaturesTilemap instance; + + private int[] map; + private float[] tileVariance; + + private SparseArray plants; + private SparseArray traps; + + public TerrainFeaturesTilemap(SparseArray plants, SparseArray traps) { + super(Assets.TERRAIN_FEATURES, new TextureFilm( Assets.TERRAIN_FEATURES, SIZE, SIZE )); + + this.plants = plants; + this.traps = traps; + + Random.seed( Dungeon.seedCurDepth()); + tileVariance = new float[Dungeon.level.map.length]; + for (int i = 0; i < tileVariance.length; i++) + tileVariance[i] = Random.Float(); + Random.seed(); + + map( Dungeon.level.map, Dungeon.level.width() ); + + instance = this; + } + + @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] = getTileVisual(i ,map[i]); + } + + @Override + public synchronized void updateMapCell(int cell) { + //update in a 3x3 grid to account for neighbours which might also be affected + if (Dungeon.level.insideMap(cell)) { + super.updateMapCell(cell - mapWidth - 1); + super.updateMapCell(cell + mapWidth + 1); + for (int i : PathFinder.NEIGHBOURS9) + data[cell + i] = getTileVisual(cell + i, map[cell + i]); + + //unless we're at the level's edge, then just do the one tile. + } else { + super.updateMapCell(cell); + data[cell] = getTileVisual(cell, map[cell]); + } + } + + private int getTileVisual(int pos, int tile){ + if (traps.get(pos) != null){ + Trap trap = traps.get(pos); + if (!trap.visible) + return -1; + else + return (trap.active ? trap.color : TrapSprite.BLACK) + (trap.shape * 16); + } + + if (plants.get(pos) != null){ + return plants.get(pos).image + 7*16; + } + + if (tile == Terrain.HIGH_GRASS){ + return 9 + 16*((Dungeon.depth-1)/5) + (tileVariance[pos] > 0.5f ? 1 : 0); + } else if (tile == Terrain.GRASS) { + return 11 + 16*((Dungeon.depth-1)/5) + (tileVariance[pos] > 0.5f ? 1 : 0); + } else if (tile == Terrain.EMBERS) { + return 13 + (tileVariance[pos] > 0.5f ? 1 : 0); + } + + return -1; + } + + public static Image tile(int pos, int tile ) { + Image img = new Image( instance.texture ); + img.frame( instance.tileset.get( instance.getTileVisual( pos, tile ) ) ); + return img; + } + + @Override + public boolean overlapsPoint( float x, float y ) { + return true; + } + + @Override + public boolean overlapsScreenPoint( int x, int y ) { + return true; + } + + @Override + protected boolean needsRender(int pos) { + return data[pos] != -1; + } +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoPlant.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoPlant.java index c822b03d6..670ceae66 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoPlant.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoPlant.java @@ -20,14 +20,19 @@ */ package com.shatteredpixel.shatteredpixeldungeon.windows; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.plants.Plant; +import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.sprites.PlantSprite; +import com.shatteredpixel.shatteredpixeldungeon.ui.TerrainFeaturesTilemap; public class WndInfoPlant extends WndTitledMessage { public WndInfoPlant( Plant plant ) { - super(new PlantSprite( plant.image ), plant.plantName, plant.desc()); + super(TerrainFeaturesTilemap.tile( plant.pos, Dungeon.level.map[plant.pos]), + plant.plantName, plant.desc()); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoTrap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoTrap.java index df2dc4cf1..bc8f6947f 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoTrap.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoTrap.java @@ -20,15 +20,16 @@ */ package com.shatteredpixel.shatteredpixeldungeon.windows; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.levels.traps.Trap; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; -import com.shatteredpixel.shatteredpixeldungeon.sprites.TrapSprite; +import com.shatteredpixel.shatteredpixeldungeon.ui.TerrainFeaturesTilemap; public class WndInfoTrap extends WndTitledMessage { public WndInfoTrap(Trap trap) { - super(new TrapSprite( trap.color + (trap.shape * 16) ), + super(TerrainFeaturesTilemap.tile( trap.pos, Dungeon.level.map[trap.pos]), trap.name, (!trap.active ? Messages.get(WndInfoTrap.class, "inactive") + "\n\n" : "") + trap.desc());