Skip to content

Commit 34e78b2

Browse files
authored
Merge pull request #422 from C7-Game/pcen/use-tilemaps-horizontal-wrapping
[4.x] TileMap: Horizontal Wrapping
2 parents fe90d18 + 71d0eae commit 34e78b2

File tree

7 files changed

+207
-180
lines changed

7 files changed

+207
-180
lines changed

C7/C7Game.tscn

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[gd_scene load_steps=15 format=3 uid="uid://cldl5nk4n61m2"]
22

33
[ext_resource type="Script" path="res://Game.cs" id="1"]
4+
[ext_resource type="Script" path="res://Map/MapViewCamera.cs" id="2_xrlqh"]
45
[ext_resource type="Script" path="res://UIElements/Advisors/Advisors.cs" id="3"]
56
[ext_resource type="Script" path="res://UIElements/UpperLeftNav/MenuButton.cs" id="4"]
67
[ext_resource type="Script" path="res://UIElements/UpperLeftNav/CivilopediaButton.cs" id="5"]
@@ -9,7 +10,6 @@
910
[ext_resource type="Script" path="res://UIElements/UnitButtons/RenameButton.cs" id="8"]
1011
[ext_resource type="Script" path="res://UIElements/Popups/PopupOverlay.cs" id="9"]
1112
[ext_resource type="Theme" uid="uid://c1jpmssnhvodi" path="res://C7Theme.tres" id="10"]
12-
[ext_resource type="Script" path="res://PlayerCamera.cs" id="11_pkhac"]
1313
[ext_resource type="Script" path="res://UIElements/UnitButtons/UnitButtons.cs" id="12"]
1414

1515
[sub_resource type="Animation" id="2"]
@@ -62,8 +62,8 @@ _data = {
6262
[node name="C7Game" type="Node2D"]
6363
script = ExtResource("1")
6464

65-
[node name="PlayerCamera" type="Camera2D" parent="."]
66-
script = ExtResource("11_pkhac")
65+
[node name="MapViewCamera" type="Camera2D" parent="."]
66+
script = ExtResource("2_xrlqh")
6767

6868
[node name="CanvasLayer" type="CanvasLayer" parent="."]
6969

C7/Civ3Map/Civ3Map.cs

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

C7/Game.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ enum GameState {
4444

4545
Stopwatch loadTimer = new Stopwatch();
4646
GlobalSingleton Global;
47-
public PlayerCamera camera;
47+
public MapViewCamera camera;
4848
bool errorOnLoad = false;
4949

5050
public override void _EnterTree() {
@@ -65,8 +65,7 @@ public override void _Ready() {
6565

6666
controller = CreateGame.createGame(Global.LoadGamePath, Global.DefaultBicPath); // Spawns engine thread
6767
Global.ResetLoadGamePath();
68-
69-
camera = GetNode("PlayerCamera") as PlayerCamera;
68+
camera = GetNode<MapViewCamera>("MapViewCamera");
7069

7170
using (var gameDataAccess = new UIGameDataAccess()) {
7271
GameMap map = gameDataAccess.gameData.map;
@@ -88,10 +87,10 @@ public override void _Ready() {
8887
camera.centerOnTile(startingSettler.location, mapView);
8988
}
9089
}
90+
camera.attachToMapView(mapView);
91+
AddChild(mapView);
9192
}
9293

93-
AddChild(mapView);
94-
9594
Toolbar = GetNode<Control>("CanvasLayer/Control/ToolBar/MarginContainer/HBoxContainer");
9695

9796
// Hide slideout bar on startup

C7/Map/MapView.cs

Lines changed: 70 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,23 @@ public static class MapZIndex {
1616
public static readonly int FogOfWar = 100;
1717
}
1818

19+
public enum HorizontalWrapState {
20+
Left, // beyond left edge of the map is visible
21+
Right, // beyond right edge of the map is visible
22+
None, // camera is entirely over the map
23+
}
24+
1925
public partial class MapView : Node2D {
2026
private string[,]terrain;
2127
private TileMap terrainTilemap;
22-
private TileMap terrainTilemapShadow;
28+
private TileMap wrappingTerrainTilemap;
2329
private TileSet terrainTileset;
2430
private TileMap tilemap;
31+
private TileMap wrappingTilemap;
2532
private TileSet tileset;
26-
private Vector2I tileSize = new Vector2I(128, 64);
33+
public Vector2I tileSize {get; private set;} = new Vector2I(128, 64);
2734
private ILogger log = LogManager.ForContext<MapView>();
35+
public bool wrapHorizontally {get; private set;}
2836
public int worldEdgeRight {get; private set;}
2937
public int worldEdgeLeft {get; private set;}
3038
private int width;
@@ -40,12 +48,13 @@ private void setShowGrid(bool value) {
4048
public void toggleGrid() {
4149
setShowGrid(!showGrid);
4250
}
51+
public int pixelWidth {get; private set;}
4352
private Game game;
4453
private GameData data;
4554
private GameMap gameMap;
4655

4756
private Dictionary<MapUnit, UnitSprite> unitSprites = new Dictionary<MapUnit, UnitSprite>();
48-
private Dictionary<City, CityScene> cityScenes = new Dictionary<City, CityScene>();
57+
private Dictionary<Tile, CityScene> cityScenes = new Dictionary<Tile, CityScene>();
4958
private CursorSprite cursor;
5059

5160
private UnitSprite spriteFor(MapUnit unit) {
@@ -69,10 +78,18 @@ public void addCity(City city, Tile tile) {
6978
CityScene scene = new CityScene(city, tile);
7079
scene.Position = tilemap.MapToLocal(stackedCoords(tile));
7180
AddChild(scene);
72-
cityScenes.Add(city, scene);
81+
cityScenes.Add(tile, scene);
82+
}
83+
84+
private Vector2I horizontalWrapOffset(HorizontalWrapState wrap) {
85+
return wrap switch {
86+
HorizontalWrapState.Left => Vector2I.Left,
87+
HorizontalWrapState.Right => Vector2I.Right,
88+
_ => Vector2I.Zero,
89+
} * pixelWidth;
7390
}
7491

75-
private void animateUnit(Tile tile, MapUnit unit) {
92+
private void animateUnit(Tile tile, MapUnit unit, HorizontalWrapState wrap) {
7693
// TODO: simplify AnimationManager and drawing animations it is unnecessarily complex
7794
// - also investigate if the custom offset tracking and SetFrame can be replaced by
7895
// engine functionality
@@ -91,8 +108,13 @@ private void animateUnit(Tile tile, MapUnit unit) {
91108
sprite.SetFrame(frame);
92109
sprite.Show();
93110

111+
Vector2 wrapOffset = horizontalWrapOffset(wrap);
112+
sprite.Translate(wrapOffset);
113+
94114
if (unit == game.CurrentlySelectedUnit) {
95-
cursor.Position = position;
115+
// TODO: just noticed cursor position maybe should not be
116+
// on sprite position which has a potential offset?
117+
cursor.Position = position + wrapOffset;
96118
cursor.Show();
97119
}
98120
}
@@ -118,15 +140,20 @@ private MapUnit selectUnitToDisplay(List<MapUnit> units) {
118140
return selected ?? interesting ?? bestDefender;
119141
}
120142

121-
public List<Tile> getVisibleTiles() {
122-
List<Tile> tiles = new List<Tile>();
143+
public List<(Tile, HorizontalWrapState)> getVisibleTiles() {
144+
List<(Tile, HorizontalWrapState)> tiles = new List<(Tile, HorizontalWrapState)>();
123145
Rect2 bounds = game.camera.getVisibleWorld();
124146
Vector2I topLeft = tilemap.LocalToMap(ToLocal(bounds.Position));
125147
Vector2I bottomRight = tilemap.LocalToMap(ToLocal(bounds.End));
126148
for (int x = topLeft.X - 1; x < bottomRight.X + 1; x++) {
127149
for (int y = topLeft.Y - 1; y < bottomRight.Y + 1; y++) {
128150
(int usX, int usY) = unstackedCoords(new Vector2I(x, y));
129-
tiles.Add(data.map.tileAt(usX, usY));
151+
HorizontalWrapState wrap = x switch {
152+
_ when x < 0 => HorizontalWrapState.Left,
153+
_ when x >= width => HorizontalWrapState.Right,
154+
_ => HorizontalWrapState.None,
155+
};
156+
tiles.Add((data.map.tileAt(usX, usY), wrap));
130157
}
131158
}
132159
return tiles;
@@ -137,44 +164,65 @@ public void updateAnimations() {
137164
s.Hide();
138165
}
139166
cursor.Hide();
140-
foreach (Tile tile in getVisibleTiles()) {
167+
foreach ((Tile tile, HorizontalWrapState wrap) in getVisibleTiles()) {
141168
MapUnit unit = selectUnitToDisplay(tile.unitsOnTile);
142169
if (unit != MapUnit.NONE) {
143-
animateUnit(tile, unit);
170+
animateUnit(tile, unit, wrap);
171+
}
172+
if (cityScenes.ContainsKey(tile)) {
173+
CityScene scene = cityScenes[tile];
174+
Vector2 position = tilemap.MapToLocal(stackedCoords(tile)) + horizontalWrapOffset(wrap);
175+
scene.Position = position;
144176
}
145177
}
146178
}
147179

180+
public void setHorizontalWrap(HorizontalWrapState state) {
181+
if (state != HorizontalWrapState.None) {
182+
Vector2I offset = horizontalWrapOffset(state);
183+
wrappingTerrainTilemap.Position = terrainTilemap.Position + offset;
184+
wrappingTilemap.Position = tilemap.Position + offset;
185+
}
186+
}
187+
148188
private void initializeTileMap() {
149189
terrainTilemap = new TileMap();
150-
terrainTilemapShadow = new TileMap();
190+
wrappingTerrainTilemap = new TileMap();
151191
terrainTileset = Civ3TerrainTileSet.Generate();
152192
terrainTilemap.TileSet = terrainTileset;
153193
terrainTilemap.Position += Vector2I.Right * (tileSize.X / 2);
154-
terrainTilemapShadow.TileSet = terrainTileset;
155-
terrainTilemapShadow.Position = terrainTilemap.Position + (Vector2I.Left * tileSize.X * width);
194+
wrappingTerrainTilemap.TileSet = terrainTileset;
156195

157196
tilemap = new TileMap{ YSortEnabled = true };
197+
wrappingTilemap = new TileMap { YSortEnabled = true };
198+
158199
tileset = TileSetLoader.LoadCiv3TileSet();
159200
tilemap.TileSet = tileset;
201+
wrappingTilemap.TileSet = tileset;
160202

161203
// create tilemap layers
162204
foreach (Layer layer in Enum.GetValues(typeof(Layer))) {
163205
if (layer != Layer.Invalid) {
164206
tilemap.AddLayer(layer.Index());
165-
tilemap.SetLayerYSortEnabled(layer.Index(), true);
207+
wrappingTilemap.AddLayer(layer.Index());
166208
if (layer != Layer.FogOfWar) {
167209
tilemap.SetLayerYSortEnabled(layer.Index(), true);
210+
wrappingTilemap.SetLayerYSortEnabled(layer.Index(), true);
168211
} else {
169212
tilemap.SetLayerZIndex(layer.Index(), MapZIndex.FogOfWar);
213+
wrappingTilemap.SetLayerZIndex(layer.Index(), MapZIndex.FogOfWar);
170214
}
171215
}
172216
}
173217

174-
tilemap.ZIndex = MapZIndex.Tiles;
218+
setHorizontalWrap(HorizontalWrapState.Right); // just put it somewhere
219+
220+
tilemap.ZIndex = 10; // need to figure out a good way to order z indices
221+
wrappingTilemap.ZIndex = 10;
175222
AddChild(tilemap);
223+
AddChild(wrappingTilemap);
176224
AddChild(terrainTilemap);
177-
// AddChild(terrainTilemapShadow);
225+
AddChild(wrappingTerrainTilemap);
178226
}
179227

180228
private void setTerrainTiles() {
@@ -211,7 +259,7 @@ void lookupAndSetTerrainTile(int x, int y, int cellX, int cellY) {
211259

212260
void setTerrainTile(Vector2I cell, int atlas, Vector2I texCoords) {
213261
terrainTilemap.SetCell(0, cell, atlas, texCoords);
214-
terrainTilemapShadow.SetCell(0, cell, atlas, texCoords);
262+
wrappingTerrainTilemap.SetCell(0, cell, atlas, texCoords);
215263
}
216264

217265
private Vector2I stackedCoords(Tile tile) {
@@ -235,8 +283,10 @@ public MapView(Game game, GameData data) {
235283
cursor = new CursorSprite();
236284
AddChild(cursor);
237285
width = gameMap.numTilesWide / 2;
286+
pixelWidth = width * tileSize.X;
238287
height = gameMap.numTilesTall;
239288
initializeTileMap();
289+
wrapHorizontally = gameMap.wrapHorizontally;
240290
terrain = new string[width, height];
241291
worldEdgeRight = (int)ToGlobal(tilemap.MapToLocal(new Vector2I(width - 1, 1))).X + tileSize.X / 2;
242292
worldEdgeLeft = (int)ToGlobal(tilemap.MapToLocal(new Vector2I(0, 0))).X - tileSize.X / 2;
@@ -276,10 +326,12 @@ private void setCell(Layer layer, Atlas atlas, Tile tile, Vector2I atlasCoords)
276326
log.Warning($"atlas id {atlas} does not have tile at {atlasCoords}");
277327
}
278328
tilemap.SetCell(layer.Index(), stackedCoords(tile), atlas.Index(), atlasCoords);
329+
wrappingTilemap.SetCell(layer.Index(), stackedCoords(tile), atlas.Index(), atlasCoords);
279330
}
280331

281332
private void eraseCell(Layer layer, Tile tile) {
282333
tilemap.EraseCell(layer.Index(), stackedCoords(tile));
334+
wrappingTilemap.EraseCell(layer.Index(), stackedCoords(tile));
283335
}
284336

285337
private void updateRoadLayer(Tile tile, bool center) {

0 commit comments

Comments
 (0)