Skip to content

Commit fe90d18

Browse files
authored
Merge pull request #421 from C7-Game/pcen/use-tilemaps-fow
[4.x] TileMap: Fog of War Layer
2 parents c6e5caa + 087c746 commit fe90d18

File tree

13 files changed

+129
-69
lines changed

13 files changed

+129
-69
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ project.lock.json
4242
*.sln.docstates
4343
C7.ini
4444
log.txt
45-
*.csproj.old
45+
*.csproj.old*
4646

4747
# Build results
4848
[Dd]ebug/

C7/Game.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,7 @@ public void processEngineMessages(GameData gameData) {
138138
}
139139
break;
140140
case MsgStartEffectAnimation mSEA:
141-
int x, y;
142-
gameData.map.tileIndexToCoords(mSEA.tileIndex, out x, out y);
143-
Tile tile = gameData.map.tileAt(x, y);
141+
Tile tile = gameData.map.tileAtIndex(mSEA.tileIndex);
144142
if (tile != Tile.NONE && controller.tileKnowledge.isTileKnown(tile))
145143
animTracker.startAnimation(tile, mSEA.effect, mSEA.completionEvent, mSEA.ending);
146144
else {
@@ -151,11 +149,17 @@ public void processEngineMessages(GameData gameData) {
151149
case MsgStartTurn mST:
152150
OnPlayerStartTurn();
153151
break;
152+
154153
case MsgCityBuilt mBC:
155154
Tile cityTile = gameData.map.tiles[mBC.tileIndex];
156155
City city = cityTile.cityAtTile;
157156
mapView.addCity(city, cityTile);
158157
break;
158+
159+
case MsgTileDiscovered mTD:
160+
Tile discoveredTile = gameData.map.tileAtIndex(mTD.tileIndex);
161+
mapView.discoverTile(discoveredTile, controller.tileKnowledge);
162+
break;
159163
}
160164
}
161165
}

C7/Map/CityScene.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public partial class CityScene : Sprite2D {
1313
private CityLabelScene cityLabelScene;
1414

1515
public CityScene(City city, Tile tile) {
16-
ZIndex = 20;
16+
ZIndex = MapZIndex.Cities;
1717
cityLabelScene = new CityLabelScene(city, tile);
1818

1919
//TODO: Generalize, support multiple city types, etc.

C7/Map/FogOfWarLayer.cs

Lines changed: 0 additions & 45 deletions
This file was deleted.

C7/Map/MapView.cs

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@
88

99
namespace C7.Map {
1010

11+
public static class MapZIndex {
12+
public static readonly int Tiles = 10;
13+
public static readonly int Cities = 20;
14+
public static readonly int Cursor = 29;
15+
public static readonly int Units = 30;
16+
public static readonly int FogOfWar = 100;
17+
}
18+
1119
public partial class MapView : Node2D {
1220
private string[,]terrain;
1321
private TileMap terrainTilemap;
@@ -155,10 +163,15 @@ private void initializeTileMap() {
155163
if (layer != Layer.Invalid) {
156164
tilemap.AddLayer(layer.Index());
157165
tilemap.SetLayerYSortEnabled(layer.Index(), true);
166+
if (layer != Layer.FogOfWar) {
167+
tilemap.SetLayerYSortEnabled(layer.Index(), true);
168+
} else {
169+
tilemap.SetLayerZIndex(layer.Index(), MapZIndex.FogOfWar);
170+
}
158171
}
159172
}
160173

161-
tilemap.ZIndex = 10; // need to figure out a good way to order z indices
174+
tilemap.ZIndex = MapZIndex.Tiles;
162175
AddChild(tilemap);
163176
AddChild(terrainTilemap);
164177
// AddChild(terrainTilemapShadow);
@@ -241,8 +254,9 @@ public MapView(Game game, GameData data) {
241254
setTerrainTiles();
242255

243256
// update each tile once to add all initial layers
257+
TileKnowledge tk = data.GetHumanPlayers().First()?.tileKnowledge;
244258
foreach (Tile tile in gameMap.tiles) {
245-
updateTile(tile);
259+
updateTile(tile, tk);
246260
}
247261
}
248262

@@ -496,13 +510,57 @@ private void updateBuildingLayer(Tile tile) {
496510
}
497511
}
498512

499-
public void updateTile(Tile tile) {
513+
// updateFogOfWarLayer returns true if the tile is visible or
514+
// semi-visible, indicating other layers should be updated.
515+
516+
private static int fogOfWarIndex(Tile tile, TileKnowledge tk) {
517+
if (tk.isTileKnown(tile)) {
518+
return 0;
519+
}
520+
int sum = 0;
521+
// HACK: edge tiles have missing directions in neighbors map
522+
if (tile.neighbors.Values.Count != 8) {
523+
return sum;
524+
}
525+
if (tk.isTileKnown(tile.neighbors[TileDirection.NORTH]) || tk.isTileKnown(tile.neighbors[TileDirection.NORTHWEST]) || tk.isTileKnown(tile.neighbors[TileDirection.NORTHEAST])) {
526+
sum += 1 * 2;
527+
}
528+
if (tk.isTileKnown(tile.neighbors[TileDirection.WEST]) || tk.isTileKnown(tile.neighbors[TileDirection.NORTHWEST]) || tk.isTileKnown(tile.neighbors[TileDirection.SOUTHWEST])) {
529+
sum += 3 * 2;
530+
}
531+
if (tk.isTileKnown(tile.neighbors[TileDirection.EAST]) || tk.isTileKnown(tile.neighbors[TileDirection.NORTHEAST]) || tk.isTileKnown(tile.neighbors[TileDirection.SOUTHEAST])) {
532+
sum += 9 * 2;
533+
}
534+
if (tk.isTileKnown(tile.neighbors[TileDirection.SOUTH]) || tk.isTileKnown(tile.neighbors[TileDirection.SOUTHWEST]) || tk.isTileKnown(tile.neighbors[TileDirection.SOUTHEAST])) {
535+
sum += 27 * 2;
536+
}
537+
return sum;
538+
}
539+
540+
private bool updateFogOfWarLayer(Tile tile, TileKnowledge tk) {
541+
if (tk.isTileKnown(tile)) {
542+
eraseCell(Layer.FogOfWar, tile);
543+
return true;
544+
}
545+
int index = fogOfWarIndex(tile, tk);
546+
setCell(Layer.FogOfWar, Atlas.FogOfWar, tile, new Vector2I(index % 9, index / 9));
547+
return index > 0; // partially visible
548+
}
549+
550+
public void updateTile(Tile tile, TileKnowledge tk) {
500551
if (tile == Tile.NONE || tile is null) {
501552
string msg = tile is null ? "null tile" : "Tile.NONE";
502553
log.Warning($"attempting to update {msg}");
503554
return;
504555
}
505556

557+
if (tk is not null) {
558+
bool visible = updateFogOfWarLayer(tile, tk);
559+
if (!visible) {
560+
return;
561+
}
562+
}
563+
506564
updateRoadLayer(tile, true);
507565

508566
if (tile.Resource != C7GameData.Resource.NONE) {
@@ -533,5 +591,17 @@ private void updateGridLayer() {
533591
tilemap.ClearLayer(Layer.Grid.Index());
534592
}
535593
}
594+
595+
public void discoverTile(Tile tile, TileKnowledge tk) {
596+
HashSet<Tile> update = new HashSet<Tile>(tile.neighbors.Values);
597+
foreach (Tile n in tile.neighbors.Values) {
598+
foreach (Tile nn in n.neighbors.Values) {
599+
update.Add(nn);
600+
}
601+
}
602+
foreach (Tile t in update) {
603+
updateTile(t, tk);
604+
}
605+
}
536606
}
537607
}

C7/Map/TileSetLoader.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using Godot;
2-
using System;
32
using System.Collections.Generic;
4-
using System.Linq;
53

64
namespace C7.Map {
75

@@ -14,6 +12,7 @@ public enum Layer {
1412
TerrainYield,
1513
Building,
1614
Grid,
15+
FogOfWar,
1716
Invalid,
1817
};
1918

@@ -46,6 +45,7 @@ public enum Atlas {
4645
TerrainBuilding,
4746
GoodyHut,
4847
Grid,
48+
FogOfWar,
4949
Invalid,
5050
}
5151

@@ -70,8 +70,8 @@ public AtlasLoader(string p, int w, int h, Vector2I rs, int y = 0) {
7070
height = h;
7171
regionSize = rs;
7272
textureOrigin = new Vector2I(0, y);
73-
source = new TileSetAtlasSource {
74-
Texture = Util.LoadTextureFromPCX(path),
73+
source = new TileSetAtlasSource{
74+
Texture = p.EndsWith("FogOfWar.pcx") ? Util.LoadFogOfWarPCX(path) : Util.LoadTextureFromPCX(path),
7575
TextureRegionSize = regionSize,
7676
};
7777
}
@@ -204,6 +204,8 @@ class TileSetLoader {
204204

205205
{Atlas.TerrainBuilding, new AtlasLoader("Art/Terrain/TerrainBuildings.pcx", 4, 4, buildingSize)},
206206
{Atlas.GoodyHut, new NonSquareAtlasLoader("Art/Terrain/goodyhuts.pcx", 3, 3, 2, buildingSize)},
207+
208+
{Atlas.FogOfWar, new NonSquareAtlasLoader("Art/Terrain/FogOfWar.pcx", 9, 9, 8, tileSize)},
207209
};
208210

209211
public static TileSet LoadCiv3TileSet() {

C7/Map/UnitSprites.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
using System;
2-
using System.Collections.Generic;
32
using C7GameData;
4-
using C7Engine;
53
using ConvertCiv3Media;
64
using Godot;
5+
using C7.Map;
76

87
// UnitSprite represents an animated unit. It's specific to a unit, action, and direction.
98
// UnitSprite comprises two sprites: a base sprite and a civ color-tinted sprite. The
@@ -12,7 +11,7 @@
1211
// use a single instance of a material and UnitSprite use a per instance uniform
1312
public partial class UnitSprite : Node2D {
1413

15-
private readonly int unitAnimZIndex = 100;
14+
private readonly int unitAnimZIndex = MapZIndex.Units;
1615
private readonly string unitShaderPath = "res://UnitTint.gdshader";
1716
private readonly string unitColorShaderParameter = "tintColor";
1817
private Shader unitShader;
@@ -76,7 +75,7 @@ public partial class CursorSprite : Node2D {
7675
private readonly string animationPath = "Art/Animations/Cursor/Cursor.flc";
7776
private readonly string animationName = "cursor";
7877
private readonly double period = 2.5;
79-
private readonly int cursorAnimZIndex = 50;
78+
private readonly int cursorAnimZIndex = MapZIndex.Cursor;
8079
private AnimatedSprite2D sprite;
8180
private int frameCount;
8281

C7/PCXToGodot.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,20 @@ public static ImageTexture getImageTextureFromPCX(Pcx pcx, int leftStart, int to
1616
return getImageTextureFromImage(image);
1717
}
1818

19+
public static ImageTexture getImageTextureFromFogOfWarPCX(Pcx pcx) {
20+
Image ImgTxtr = ByteArrayToImage(pcx.ColorIndices, pcx.Palette, pcx.Width, pcx.Height);
21+
for (int x = 0; x < ImgTxtr.GetWidth(); x++) {
22+
for (int y = 0; y < ImgTxtr.GetHeight(); y++) {
23+
Color pixel = ImgTxtr.GetPixel(x, y);
24+
if (pixel.A > 0) {
25+
Color transparent = new Color(pixel.R, pixel.G, pixel.B, 1f - pixel.R);
26+
ImgTxtr.SetPixel(x, y, transparent);
27+
}
28+
}
29+
}
30+
return getImageTextureFromImage(ImgTxtr);
31+
}
32+
1933
/**
2034
* This method is for cases where we want to use components of multiple PCXs in a texture, such as for the popup background.
2135
**/

C7/Util.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ static public ImageTexture LoadTextureFromPCX(string relPath, int leftStart, int
221221
return texture;
222222
}
223223

224+
static public ImageTexture LoadFogOfWarPCX(string relPath) => PCXToGodot.getImageTextureFromFogOfWarPCX(LoadPCX(relPath));
225+
224226
private static Dictionary<string, Pcx> PcxCache = new Dictionary<string, Pcx>();
225227

226228
/**

C7Engine/EntryPoints/MessageToUI.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,12 @@ public MsgCityBuilt(Tile tile) {
5151

5252
public class MsgStartTurn : MessageToUI {}
5353

54+
public class MsgTileDiscovered : MessageToUI {
55+
public int tileIndex;
56+
57+
public MsgTileDiscovered(Tile tile) {
58+
this.tileIndex = EngineStorage.gameData.map.tileCoordsToIndex(tile.xCoordinate, tile.yCoordinate);
59+
}
60+
}
61+
5462
}

0 commit comments

Comments
 (0)