Skip to content

Commit c6e5caa

Browse files
authored
Merge pull request #412 from C7-Game/pcen/use-tilemaps-render-cities
Godot 4 Render Cities on TileMap
2 parents 510d01c + b5521ec commit c6e5caa

File tree

9 files changed

+106
-132
lines changed

9 files changed

+106
-132
lines changed

C7/C7Game.tscn

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -257,16 +257,6 @@ libraries = {
257257
[connection signal="ShowSpecificAdvisor" from="." to="CanvasLayer/Advisor" method="OnShowSpecificAdvisor"]
258258
[connection signal="TurnEnded" from="." to="CanvasLayer/Control/GameStatus" method="OnTurnEnded"]
259259
[connection signal="TurnStarted" from="." to="CanvasLayer/Control/GameStatus" method="OnTurnStarted"]
260-
[connection signal="BlinkyEndTurnButtonPressed" from="CanvasLayer/GameStatus" to="." method="OnPlayerEndTurn"]
261-
[connection signal="toggled" from="CanvasLayer/SlideOutBar/SlideToggle" to="." method="_on_SlideToggle_toggled"]
262-
[connection signal="pressed" from="CanvasLayer/SlideOutBar/VBoxContainer/DownButton" to="." method="_on_DownButton_pressed"]
263-
[connection signal="pressed" from="CanvasLayer/SlideOutBar/VBoxContainer/RightButton" to="." method="_on_RightButton_pressed"]
264-
[connection signal="pressed" from="CanvasLayer/SlideOutBar/VBoxContainer/LeftButton" to="." method="_on_LeftButton_pressed"]
265-
[connection signal="pressed" from="CanvasLayer/SlideOutBar/VBoxContainer/UpButton" to="." method="_on_UpButton_pressed"]
266-
[connection signal="value_changed" from="CanvasLayer/SlideOutBar/VBoxContainer/Zoom" to="." method="onSliderZoomChanged"]
267-
[connection signal="pressed" from="CanvasLayer/SlideOutBar/VBoxContainer/QuitButton" to="." method="_on_QuitButton_pressed"]
268-
[connection signal="pressed" from="CanvasLayer/ToolBar/MarginContainer/HBoxContainer/AdvisorButton" to="CanvasLayer/Advisor" method="ShowLatestAdvisor"]
269-
[connection signal="pressed" from="CanvasLayer/ToolBar/MarginContainer/HBoxContainer/UiBarEndTurnButton" to="." method="_onEndTurnButtonPressed"]
270260
[connection signal="BuildCity" from="CanvasLayer/PopupOverlay" to="." method="OnBuildCity"]
271261
[connection signal="HidePopup" from="CanvasLayer/PopupOverlay" to="CanvasLayer/PopupOverlay" method="OnHidePopup"]
272262
[connection signal="UnitDisbanded" from="CanvasLayer/PopupOverlay" to="." method="OnUnitDisbanded"]

C7/Game.cs

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,6 @@ public override void _Ready() {
9494

9595
Toolbar = GetNode<Control>("CanvasLayer/Control/ToolBar/MarginContainer/HBoxContainer");
9696

97-
//TODO: What was this supposed to do? It throws errors and occasinally causes crashes now, because _OnViewportSizeChanged doesn't exist
98-
// GetTree().Root.Connect("size_changed",new Callable(this,"_OnViewportSizeChanged"));
99-
10097
// Hide slideout bar on startup
10198
_on_SlideToggle_toggled(false);
10299

@@ -154,6 +151,11 @@ public void processEngineMessages(GameData gameData) {
154151
case MsgStartTurn mST:
155152
OnPlayerStartTurn();
156153
break;
154+
case MsgCityBuilt mBC:
155+
Tile cityTile = gameData.map.tiles[mBC.tileIndex];
156+
City city = cityTile.cityAtTile;
157+
mapView.addCity(city, cityTile);
158+
break;
157159
}
158160
}
159161
}
@@ -220,11 +222,10 @@ public override void _Process(double delta) {
220222

221223
// If "location" is not already near the center of the screen, moves the camera to bring it into view.
222224
public void ensureLocationIsInView(Tile location) {
223-
// TODO: implement
224225
if (controller.tileKnowledge.isTileKnown(location) && location != Tile.NONE) {
225-
// Vector2 relativeScreenLocation = oldMapView.screenLocationOfTile(location, true) / oldMapView.getVisibleAreaSize();
226-
// if (relativeScreenLocation.DistanceTo(new Vector2((float)0.5, (float)0.5)) > 0.30)
227-
// oldMapView.centerCameraOnTile(location);
226+
if (!camera.isTileInView(location, mapView)) {
227+
camera.centerOnTile(location, mapView);
228+
}
228229
}
229230
}
230231

@@ -341,18 +342,6 @@ public override void _UnhandledInput(InputEvent @event) {
341342
if (to_select != null && to_select.owner == controller)
342343
setSelectedUnit(to_select);
343344
}
344-
GD.Print($"tile: {tile.xCoordinate}, {tile.yCoordinate}: {tile.baseTerrainType.Key} - {tile.overlayTerrainType.Key}");
345-
int left = mapView.worldEdgeLeft;
346-
int right = mapView.worldEdgeRight;
347-
int camLeft = (int)camera.getVisibleWorld().Position.X;
348-
int camRight = (int)camera.getVisibleWorld().End.X;
349-
GD.Print(camera.getVisibleWorld().End);
350-
if (camLeft <= left) {
351-
GD.Print($"left is visible - world: {left}, cam: {camLeft}");
352-
}
353-
if (camRight >= right) {
354-
GD.Print($"right is visible - world: {right}, cam: {camRight}");
355-
}
356345
}
357346
}
358347
}
@@ -529,7 +518,6 @@ private void processActions() {
529518
if (Input.IsActionJustPressed(C7Action.UnitBuildRoad) && CurrentlySelectedUnit.canBuildRoad()) {
530519
new MsgBuildRoad(CurrentlySelectedUnit.guid).send();
531520
}
532-
533521
}
534522

535523
private void GetNextAutoselectedUnit(GameData gameData) {

C7/Map/CityLabelScene.cs

Lines changed: 63 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ public partial class CityLabelScene : Node2D {
1111

1212
private City city;
1313
private Tile tile;
14-
private Vector2I tileCenter;
1514

1615
private ImageTexture cityTexture;
1716

@@ -37,6 +36,11 @@ public partial class CityLabelScene : Node2D {
3736
private static Theme popSizeTheme = new Theme();
3837

3938
private int lastLabelWidth = 0;
39+
private int lastTurnsUntilGrowth;
40+
private int lastTurnsUntilProductFinished;
41+
private int lastCitySize;
42+
private string lastProductionName;
43+
private bool wasCapital;
4044

4145
static CityLabelScene() {
4246
smallFontTheme.DefaultFont = smallFont;
@@ -54,94 +58,105 @@ static CityLabelScene() {
5458
nonEmbassyStar = PCXToGodot.getImageFromPCX(cityIcons, 20, 1, 18, 18);
5559
}
5660

57-
public CityLabelScene(City city, Tile tile, Vector2I tileCenter) {
61+
public CityLabelScene(City city, Tile tile) {
5862
this.city = city;
5963
this.tile = tile;
60-
this.tileCenter = tileCenter;
61-
6264

6365
labelTextureRect.MouseFilter = Control.MouseFilterEnum.Ignore;
6466
cityNameLabel.MouseFilter = Control.MouseFilterEnum.Ignore;
6567
productionLabel.MouseFilter = Control.MouseFilterEnum.Ignore;
6668
popSizeLabel.MouseFilter = Control.MouseFilterEnum.Ignore;
6769

70+
cityNameLabel.Text = city.name;
6871
AddChild(labelTextureRect);
6972
AddChild(cityNameLabel);
7073
AddChild(productionLabel);
7174
AddChild(popSizeLabel);
75+
76+
cityNameLabel.Theme = smallFontTheme;
77+
cityNameLabel.OffsetTop = 24;
78+
79+
productionLabel.Theme = smallFontTheme;
80+
productionLabel.OffsetTop = 36;
81+
82+
popSizeLabel.Theme = popSizeTheme;
83+
popSizeLabel.OffsetTop = 28;
84+
85+
lastTurnsUntilGrowth = city.TurnsUntilGrowth();
86+
lastTurnsUntilProductFinished = city.TurnsUntilProductionFinished();
87+
lastCitySize = city.size;
88+
lastProductionName = city.itemBeingProduced.name;
89+
wasCapital = city.IsCapital();
90+
91+
resize(lastTurnsUntilGrowth, lastTurnsUntilProductFinished, lastCitySize, lastProductionName, wasCapital);
7292
}
7393

74-
public override void _Draw() {
75-
base._Draw();
94+
private string getCityNameAndGrowthString(int turnsUntilGrowth) {
95+
string turnsUntilGrowthText = turnsUntilGrowth == int.MaxValue || turnsUntilGrowth < 0 ? "- -" : turnsUntilGrowth.ToString();
96+
return $"{city.name} : {turnsUntilGrowthText}";
97+
}
7698

77-
int turnsUntilGrowth = city.TurnsUntilGrowth();
78-
string turnsUntilGrowthText = turnsUntilGrowth == int.MaxValue || turnsUntilGrowth < 0 ? "- -" : "" + turnsUntilGrowth;
79-
string cityNameAndGrowth = $"{city.name} : {turnsUntilGrowthText}";
80-
string productionDescription = city.itemBeingProduced.name + " : " + city.TurnsUntilProductionFinished();
99+
private void resize(int turnsUntilGrowth, int turnsUntilProductionFinished, int citySize, string productionName, bool isCapital) {
100+
string productionDescription = $"{productionName} : {turnsUntilProductionFinished}";
101+
int productionDescriptionWidth = (int)smallFont.GetStringSize(productionDescription).X;
81102

103+
string cityNameAndGrowth = getCityNameAndGrowthString(turnsUntilGrowth);
82104
int cityNameAndGrowthWidth = (int)smallFont.GetStringSize(cityNameAndGrowth).X;
83-
int productionDescriptionWidth = (int)smallFont.GetStringSize(productionDescription).X;
84105
int maxTextWidth = Math.Max(cityNameAndGrowthWidth, productionDescriptionWidth);
106+
int cityLabelWidth = maxTextWidth + (isCapital? 70 : 45); //TODO: Is 65 right? 70? Will depend on whether it's capital, too
85107

86-
int cityLabelWidth = maxTextWidth + (city.IsCapital()? 70 : 45); //TODO: Is 65 right? 70? Will depend on whether it's capital, too
87-
int textAreaWidth = cityLabelWidth - (city.IsCapital() ? 50 : 25);
108+
int textAreaWidth = cityLabelWidth - (isCapital ? 50 : 25);
88109
if (log.IsEnabled(LogEventLevel.Verbose)) {
89-
log.Verbose("Width of city name = " + maxTextWidth);
90110
log.Verbose("City label width: " + cityLabelWidth);
91111
log.Verbose("Text area width: " + textAreaWidth);
92112
}
93-
94113
if (cityLabelWidth != lastLabelWidth) {
95114
Image labelBackground = CreateLabelBackground(cityLabelWidth, city, textAreaWidth);
96-
cityLabel = ImageTexture.CreateFromImage(labelBackground);
115+
cityLabel = ImageTexture.CreateFromImage(labelBackground);
97116
lastLabelWidth = cityLabelWidth;
117+
labelTextureRect.Texture = cityLabel;
118+
labelTextureRect.OffsetLeft = (cityLabelWidth / -2);
119+
labelTextureRect.OffsetTop = 24;
98120
}
99-
100-
DrawLabelOnScreen(tileCenter, cityLabelWidth, city, cityLabel);
101-
DrawTextOnLabel(tileCenter, cityNameAndGrowthWidth, productionDescriptionWidth, city, cityNameAndGrowth, productionDescription, cityLabelWidth);
102-
}
103-
104-
private void DrawLabelOnScreen(Vector2I tileCenter, int cityLabelWidth, City city, ImageTexture cityLabel)
105-
{
106-
labelTextureRect.OffsetLeft = tileCenter.X + (cityLabelWidth / -2);
107-
labelTextureRect.OffsetTop = tileCenter.Y + 24;
108-
labelTextureRect.Texture = cityLabel;
109-
}
110-
111-
private void DrawTextOnLabel(Vector2I tileCenter, int cityNameAndGrowthWidth, int productionDescriptionWidth, City city, string cityNameAndGrowth, string productionDescription, int cityLabelWidth) {
112-
113-
//Destination for font is based on lower-left of baseline of font, not upper left as for blitted rectangles
114-
int cityNameOffset = cityNameAndGrowthWidth / -2;
115-
int prodDescriptionOffset = productionDescriptionWidth / -2;
116-
if (!city.IsCapital()) {
121+
int cityNameOffset = cityNameAndGrowthWidth / -2 - 8;
122+
int prodDescriptionOffset = productionDescriptionWidth / -2 - 8;
123+
if (!isCapital) {
117124
cityNameOffset += 12;
118125
prodDescriptionOffset += 12;
119126
}
120-
121-
cityNameLabel.Theme = smallFontTheme;
122127
cityNameLabel.Text = cityNameAndGrowth;
123-
cityNameLabel.OffsetLeft = tileCenter.X + cityNameOffset;
124-
cityNameLabel.OffsetTop = tileCenter.Y + 22;
128+
cityNameLabel.OffsetLeft = cityNameOffset;
125129

126-
productionLabel.Theme = smallFontTheme;
127130
productionLabel.Text = productionDescription;
128-
productionLabel.OffsetLeft = tileCenter.X + prodDescriptionOffset;
129-
productionLabel.OffsetTop = tileCenter.Y + 32;
131+
productionLabel.OffsetLeft = prodDescriptionOffset;
130132

131-
//City pop size
132-
string popSizeString = "" + city.size;
133+
string popSizeString = citySize.ToString();
133134
int popSizeWidth = (int)midSizedFont.GetStringSize(popSizeString).X;
134135
int popSizeOffset = LEFT_RIGHT_BOXES_WIDTH / 2 - popSizeWidth / 2;
135136

136-
popSizeLabel.Theme = popSizeTheme;
137-
138-
if (city.TurnsUntilGrowth() < 0) {
137+
if (turnsUntilGrowth < 0) {
139138
popSizeLabel.Theme = popThemeRed;
140139
}
141140

142141
popSizeLabel.Text = popSizeString;
143-
popSizeLabel.OffsetLeft = tileCenter.X + cityLabelWidth / -2 + popSizeOffset;
144-
popSizeLabel.OffsetTop = tileCenter.Y + 22;
142+
popSizeLabel.OffsetLeft = cityLabelWidth / -2 + popSizeOffset;
143+
}
144+
145+
public override void _Process(double delta) {
146+
int turnsUntilGrowth = city.TurnsUntilGrowth();
147+
int turnsUntilProductionFinished = city.TurnsUntilProductionFinished();
148+
int citySize = city.size;
149+
string productionName = city.itemBeingProduced.name;
150+
bool isCaptial = city.IsCapital();
151+
152+
if (turnsUntilGrowth != lastTurnsUntilGrowth || turnsUntilProductionFinished != lastTurnsUntilProductFinished || citySize != lastCitySize || productionName != lastProductionName || isCaptial != wasCapital) {
153+
lastTurnsUntilGrowth = turnsUntilGrowth;
154+
lastTurnsUntilProductFinished = turnsUntilProductionFinished;
155+
lastCitySize = citySize;
156+
lastProductionName = productionName;
157+
wasCapital = isCaptial;
158+
resize(turnsUntilGrowth, turnsUntilProductionFinished, citySize, productionName, isCaptial);
159+
}
145160
}
146161

147162
private Image CreateLabelBackground(int cityLabelWidth, City city, int textAreaWidth)

C7/Map/CityLayer.cs

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

C7/Map/CityScene.cs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@
44
using Serilog;
55

66
namespace C7.Map {
7-
public partial class CityScene : Node2D {
7+
public partial class CityScene : Sprite2D {
88
private ILogger log = LogManager.ForContext<CityScene>();
99

1010
private readonly Vector2 citySpriteSize;
1111

1212
private ImageTexture cityTexture;
13-
private TextureRect cityGraphics = new TextureRect();
1413
private CityLabelScene cityLabelScene;
1514

16-
public CityScene(City city, Tile tile, Vector2I tileCenter) {
17-
cityLabelScene = new CityLabelScene(city, tile, tileCenter);
15+
public CityScene(City city, Tile tile) {
16+
ZIndex = 20;
17+
cityLabelScene = new CityLabelScene(city, tile);
1818

1919
//TODO: Generalize, support multiple city types, etc.
2020
Pcx pcx = Util.LoadPCX("Art/Cities/rMIDEAST.PCX");
@@ -23,18 +23,9 @@ public CityScene(City city, Tile tile, Vector2I tileCenter) {
2323
cityTexture = Util.LoadTextureFromPCX("Art/Cities/rMIDEAST.PCX", 0, 0, width, height);
2424
citySpriteSize = new Vector2(width, height);
2525

26-
cityGraphics.OffsetLeft = tileCenter.X - (float)0.5 * citySpriteSize.X;
27-
cityGraphics.OffsetTop = tileCenter.Y - (float)0.5 * citySpriteSize.Y;
28-
cityGraphics.MouseFilter = Control.MouseFilterEnum.Ignore;
29-
cityGraphics.Texture = cityTexture;
26+
Texture = cityTexture;
3027

31-
AddChild(cityGraphics);
3228
AddChild(cityLabelScene);
3329
}
34-
35-
public override void _Draw() {
36-
base._Draw();
37-
cityLabelScene._Draw();
38-
}
3930
}
4031
}

C7/Map/MapView.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public void toggleGrid() {
3737
private GameMap gameMap;
3838

3939
private Dictionary<MapUnit, UnitSprite> unitSprites = new Dictionary<MapUnit, UnitSprite>();
40+
private Dictionary<City, CityScene> cityScenes = new Dictionary<City, CityScene>();
4041
private CursorSprite cursor;
4142

4243
private UnitSprite spriteFor(MapUnit unit) {
@@ -55,6 +56,14 @@ private Vector2 getSpriteLocalPosition(Tile tile, MapUnit.Appearance appearance)
5556
return position + offset;
5657
}
5758

59+
public void addCity(City city, Tile tile) {
60+
log.Debug($"adding city at tile ({tile.xCoordinate}, {tile.yCoordinate})");
61+
CityScene scene = new CityScene(city, tile);
62+
scene.Position = tilemap.MapToLocal(stackedCoords(tile));
63+
AddChild(scene);
64+
cityScenes.Add(city, scene);
65+
}
66+
5867
private void animateUnit(Tile tile, MapUnit unit) {
5968
// TODO: simplify AnimationManager and drawing animations it is unnecessarily complex
6069
// - also investigate if the custom offset tracking and SetFrame can be replaced by

C7/PlayerCamera.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,13 @@ public void centerOnTile(Tile tile, MapView map) {
4444
Vector2 target = map.tileToLocal(tile);
4545
Position = target;
4646
}
47+
48+
public bool isTileInView(Tile tile, MapView map) {
49+
Rect2 visible = getVisibleWorld();
50+
Vector2 target = map.tileToLocal(tile);
51+
float size = 30;
52+
target -= Vector2.One * (size / 2);
53+
Rect2 boundingBox = new Rect2(target, size, size);
54+
return visible.Encloses(boundingBox);
55+
}
4756
}

C7Engine/EntryPoints/CityInteractions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System.Linq;
21
using C7Engine.AI;
32

43
namespace C7Engine
@@ -23,6 +22,7 @@ public static void BuildCity(int x, int y, string playerGuid, string name)
2322
owner.cities.Add(newCity);
2423
tileWithNewCity.cityAtTile = newCity;
2524
tileWithNewCity.overlays.road = true;
25+
new MsgCityBuilt(tileWithNewCity).send(); // UI will add city to the map view
2626
}
2727

2828
public static void DestroyCity(int x, int y) {

0 commit comments

Comments
 (0)