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 36809d16a..65583882c 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java @@ -27,7 +27,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Badges; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTerrainTilemap; import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap; -import com.shatteredpixel.shatteredpixeldungeon.FogOfWar; +import com.shatteredpixel.shatteredpixeldungeon.tiles.FogOfWar; import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon; import com.shatteredpixel.shatteredpixeldungeon.Statistics; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; @@ -59,6 +59,7 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.DiscardedItemSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.HeroSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite; import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTileSheet; +import com.shatteredpixel.shatteredpixeldungeon.tiles.WallBlockingTilemap; import com.shatteredpixel.shatteredpixeldungeon.ui.ActionIndicator; import com.shatteredpixel.shatteredpixeldungeon.ui.AttackIndicator; import com.shatteredpixel.shatteredpixeldungeon.ui.Banner; @@ -114,6 +115,7 @@ public class GameScene extends PixelScene { private DungeonTerrainTilemap tiles; private TerrainFeaturesTilemap terrainFeatures; private DungeonWallsTilemap walls; + private WallBlockingTilemap wallBlocking; private FogOfWar fog; private HeroSprite hero; @@ -241,6 +243,9 @@ public class GameScene extends PixelScene { walls = new DungeonWallsTilemap(); add(walls); + wallBlocking = new WallBlockingTilemap(); + add (wallBlocking); + fog = new FogOfWar( Dungeon.level.width(), Dungeon.level.height() ); add( fog ); @@ -723,13 +728,16 @@ public class GameScene extends PixelScene { } public static void updateFog(){ - if (scene != null) + if (scene != null) { scene.fog.updateFog(); + scene.wallBlocking.updateMap(); + } } public static void updateFog(int x, int y, int w, int h){ if (scene != null) { scene.fog.updateFogArea(x, y, w, h); + scene.wallBlocking.updateArea(x, y, w, h); } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/FogOfWar.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/FogOfWar.java similarity index 50% rename from core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/FogOfWar.java rename to core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/FogOfWar.java index 21bea1779..9a29ccd34 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/FogOfWar.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/FogOfWar.java @@ -18,11 +18,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see */ -package com.shatteredpixel.shatteredpixeldungeon; +package com.shatteredpixel.shatteredpixeldungeon.tiles; import android.opengl.GLES20; -import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon; import com.watabou.gltextures.SmartTexture; import com.watabou.gltextures.TextureCache; import com.watabou.glwrap.Texture; @@ -37,24 +38,37 @@ import java.nio.IntBuffer; public class FogOfWar extends Image { - private static final int VISIBLE[] = new int[]{0xAA000000, 0x55000000, //-2 and -1 brightness - 0x00000000, //0 brightness - 0x00000000, 0x00000000}; //1 and 2 brightness + //first index is visibility type, second is brightness level + private static final int FOG_COLORS[][] = new int[][]{{ + //visible + 0xAA000000, 0x55000000, //-2 and -1 brightness + 0x00000000, //0 brightness + 0x00000000, 0x00000000 //1 and 2 brightness + }, { + //visited + 0xEE000000, 0xDD000000, + 0xCC000000, + 0x99000000, 0x66000000 + }, { + //mapped + 0xEE442211, 0xDD442211, + 0xCC442211, + 0x99442211, 0x66442211 + }, { + //invisible + 0xFF000000, 0xFF000000, + 0xFF000000, + 0xFF000000, 0xFF000000 + }}; - private static final int VISITED[] = new int[]{0xEE000000, 0xDD000000, - 0xCC000000, - 0x99000000, 0x66000000}; - - private static final int MAPPED[] = new int[]{0xEE442211, 0xDD442211, - 0xCC442211, - 0x99442211, 0x66442211}; - - private static final int INVISIBLE[]= new int[]{0xFF000000, 0xFF000000, - 0xFF000000, - 0xFF000000, 0xFF000000}; + private static final int VISIBLE = 0; + private static final int VISITED = 1; + private static final int MAPPED = 2; + private static final int INVISIBLE = 3; private int mapWidth; private int mapHeight; + private int mapLength; private int pWidth; private int pHeight; @@ -73,6 +87,7 @@ public class FogOfWar extends Image { this.mapWidth = mapWidth; this.mapHeight = mapHeight; + mapLength = mapHeight * mapWidth; pWidth = mapWidth * PIX_PER_TILE; pHeight = mapHeight * PIX_PER_TILE; @@ -113,30 +128,100 @@ public class FogOfWar extends Image { updating = new Rect(updated); updated.setEmpty(); } + + private boolean[] visible; + private boolean[] visited; + private boolean[] mapped; + private int brightness; private void updateTexture( boolean[] visible, boolean[] visited, boolean[] mapped ) { + this.visible = visible; + this.visited = visited; + this.mapped = mapped; + this.brightness = ShatteredPixelDungeon.brightness() + 2; moveToUpdating(); FogTexture fog = (FogTexture)texture; - int brightness = ShatteredPixelDungeon.brightness() + 2; - + int cellIndex; + int[] colorArray = new int[PIX_PER_TILE*PIX_PER_TILE]; for (int i=updating.top; i < updating.bottom; i++) { int cell = mapWidth * i + updating.left; - //fog.pixels.position((width2) * i + updating.left); for (int j=updating.left; j < updating.right; j++) { - if (cell >= Dungeon.level.length()) { - //do nothing - } else if (visible[cell]) { - fillCell(j, i, VISIBLE[brightness]); - } else if (visited[cell]) { - fillCell(j, i, VISITED[brightness]); - } else if (mapped[cell] ) { - fillCell(j, i, MAPPED[brightness]); - } else { - fillCell(j, i, INVISIBLE[brightness]); + + if (cell >= Dungeon.level.length()) continue; //do nothing + + if (!visible[cell] && !visited[cell] && !mapped[cell]){ + fillCell(j, i, FOG_COLORS[INVISIBLE][brightness]); + cell++; + continue; } + + //triggers on wall tiles or sideways doors + if (DungeonTileSheet.wallStitcheable.contains(Dungeon.level.map[cell]) || + ( DungeonTileSheet.doorTiles.contains(Dungeon.level.map[cell]) + && cell + mapWidth < mapLength + && DungeonTileSheet.wallStitcheable.contains(Dungeon.level.map[cell + mapWidth]))) { + cellIndex = getColorIndexForCell(cell); + + if (cell + mapWidth < mapLength){ + if (!DungeonTileSheet.wallStitcheable.contains(Dungeon.level.map[cell + mapWidth]) + && getColorIndexForCell(cell + mapWidth) > cellIndex) { + cellIndex = getColorIndexForCell(cell + mapWidth); + } + + if (cell % mapWidth != 0){ + if (DungeonTileSheet.wallStitcheable.contains(Dungeon.level.map[cell - 1])){ + if (getColorIndexForCell(cell - 1 + mapWidth) > cellIndex) + colorArray[0] = colorArray[2] = FOG_COLORS[getColorIndexForCell(cell - 1 + mapWidth)][brightness]; + else + colorArray[0] = colorArray[2] = FOG_COLORS[cellIndex][brightness]; + } else { + if (getColorIndexForCell(cell - 1) > cellIndex) + colorArray[0] = colorArray[2] = FOG_COLORS[getColorIndexForCell(cell - 1)][brightness]; + else + colorArray[0] = colorArray[2] = FOG_COLORS[cellIndex][brightness]; + } + } else { + colorArray[0] = colorArray[2] = FOG_COLORS[cellIndex][brightness]; + } + + if ((cell+1) % mapWidth != 0){ + if (DungeonTileSheet.wallStitcheable.contains(Dungeon.level.map[cell + 1])){ + if (getColorIndexForCell(cell + 1 + mapWidth) > cellIndex) + colorArray[1] = colorArray[3] = FOG_COLORS[getColorIndexForCell(cell + 1 + mapWidth)][brightness]; + else + colorArray[1] = colorArray[3] = FOG_COLORS[cellIndex][brightness]; + } else { + if (getColorIndexForCell(cell + 1) > cellIndex) + colorArray[1] = colorArray[3] = FOG_COLORS[getColorIndexForCell(cell + 1)][brightness]; + else + colorArray[1] = colorArray[3] = FOG_COLORS[cellIndex][brightness]; + } + } else { + colorArray[1] = colorArray[3] = FOG_COLORS[cellIndex][brightness]; + } + + } else { + if (cell % mapWidth != 0 && getColorIndexForCell(cell - 1) > cellIndex) { + colorArray[0] = colorArray[2] = FOG_COLORS[getColorIndexForCell(cell - 1)][brightness]; + } else { + colorArray[0] = colorArray[2] = FOG_COLORS[cellIndex][brightness]; + } + + if ((cell+1) % mapWidth != 0 && getColorIndexForCell(cell + 1) > cellIndex) { + colorArray[1] = colorArray[3] = FOG_COLORS[getColorIndexForCell(cell + 1)][brightness]; + } else { + colorArray[1] = colorArray[3] = FOG_COLORS[cellIndex][brightness]; + } + } + + fillCell(j, i, colorArray); + } else { + fillCell(j, i, FOG_COLORS[getColorIndexForCell(cell)][brightness]); + } + cell++; } } @@ -148,6 +233,29 @@ public class FogOfWar extends Image { } + private int getColorIndexForCell( int cell ){ + + if (visible[cell]) { + return VISIBLE; + } else if (visited[cell]) { + return VISITED; + } else if (mapped[cell] ) { + return MAPPED; + } else { + return INVISIBLE; + } + } + + private void fillCell( int x, int y, int[] colors){ + FogTexture fog = (FogTexture)texture; + for (int i = 0; i < PIX_PER_TILE; i++){ + fog.pixels.position(((y * PIX_PER_TILE)+i)*width2 + x * PIX_PER_TILE); + for (int j = 0; j < PIX_PER_TILE; j++) { + fog.pixels.put(colors[i*PIX_PER_TILE + j]); + } + } + } + private void fillCell( int x, int y, int color){ FogTexture fog = (FogTexture)texture; for (int i = 0; i < PIX_PER_TILE; i++){ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/WallBlockingTilemap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/WallBlockingTilemap.java new file mode 100644 index 000000000..e68fe31ca --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/tiles/WallBlockingTilemap.java @@ -0,0 +1,141 @@ +/* + * 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.tiles; + +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.Tilemap; + + +public class WallBlockingTilemap extends Tilemap { + + public static final int SIZE = 16; + + private static final int BLOCK_NONE = 0; + private static final int BLOCK_RIGHT = 1; + private static final int BLOCK_LEFT = 2; + private static final int BLOCK_ALL = 3; + + public WallBlockingTilemap() { + super("wall_blocking.png", new TextureFilm( "wall_blocking.png", SIZE, SIZE ) ); + map( new int[Dungeon.level.length()], Dungeon.level.width()); + } + + @Override + public synchronized void updateMap() { + super.updateMap(); + for (int i = 0; i < data.length; i++) + updateMapCell(i); + } + + @Override + public synchronized void updateMapCell(int cell) { + int prev = data[cell]; + int curr; + + //no point in blocking tiles that are already obscured by fog + if (fogHidden(cell) && fogHidden(cell - mapWidth)){ + curr = BLOCK_NONE; + + } else if (DungeonTileSheet.wallStitcheable.contains(Dungeon.level.map[cell])) { + if (cell + mapWidth < Dungeon.level.map.length) { + if (!DungeonTileSheet.wallStitcheable.contains(Dungeon.level.map[cell + mapWidth])) { + if (fogHidden(cell + mapWidth)) { + curr = BLOCK_ALL; + } else { + curr = BLOCK_NONE; + } + } else { + curr = BLOCK_NONE; + + if ((cell + 1) % mapWidth != 0) { + + if (!DungeonTileSheet.wallStitcheable.contains(Dungeon.level.map[cell + 1])){ + if (fogHidden(cell + 1)) { + curr += 1; + } + } else { + if (fogHidden(cell + 1 + mapWidth)){ + curr += 1; + } + } + + } + + if (cell % mapWidth != 0) { + + if (!DungeonTileSheet.wallStitcheable.contains(Dungeon.level.map[cell - 1])){ + if (fogHidden(cell - 1)) { + curr += 2; + } + } else { + if (fogHidden(cell - 1 + mapWidth)){ + curr += 2; + } + } + + } + + } + + } else { + curr = BLOCK_NONE; + + if ((cell + 1) % mapWidth != 0 && fogHidden(cell + 1)) { + curr += 1; + } + + if (cell % mapWidth != 0 && fogHidden(cell - 1)) { + curr += 2; + } + } + + } else { + curr = BLOCK_NONE; + } + + if (prev != curr){ + data[cell] = curr; + super.updateMapCell(cell); + } + } + + private boolean fogHidden(int cell){ + if (cell < 0 || cell >= Dungeon.level.length()) return false; + return (!Dungeon.level.visited[cell] && !Dungeon.level.mapped[cell]); + } + + public synchronized void updateArea(int x, int y, int w, int h) { + int cell; + for (int i = x; i <= x+w; i++){ + for (int j = y; j <= y+h; j++){ + cell = i + j*mapWidth; + if (cell < data.length) + updateMapCell(cell); + } + } + } + + @Override + protected boolean needsRender(int pos) { + return data[pos] != BLOCK_NONE; + } +}