From ba366157fdfb55bf4f3308d3aaf6db23074404a4 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Fri, 8 Aug 2025 16:03:25 +0200 Subject: [PATCH] Add Godot conversion extensions and update related code for integration --- Lib/Civilization.Core/Vec2i.cs | 3 +++ global.json | 5 +++++ .../Civilization.GodotIntegration/CityRenderer.cs | 3 ++- .../Civilization.GodotIntegration.csproj | 3 +-- .../Civilization.GodotIntegration/GameController.cs | 7 ++++--- .../Civilization.GodotIntegration/InputSystem.cs | 3 ++- .../Civilization.GodotIntegration/MapRenderer.cs | 3 ++- .../SelectedUnitPanel.cs | 12 ++++++------ .../SelectionSystem.cs | 4 +++- .../Civilization.GodotIntegration/UiController.cs | 2 +- .../Civilization.GodotIntegration/UnitRenderer.cs | 3 ++- .../Utils/GodotConversionExtensions.cs | 13 +++++++++++++ godot_game/Scenes/world.tscn | 3 ++- godot_game/UI/selected_unit_panel.tscn | 6 ++---- godot_game/project.godot | 3 ++- 15 files changed, 50 insertions(+), 23 deletions(-) create mode 100644 global.json create mode 100644 godot_game/Civilization.GodotIntegration/Utils/GodotConversionExtensions.cs diff --git a/Lib/Civilization.Core/Vec2i.cs b/Lib/Civilization.Core/Vec2i.cs index 93bd396..1997f02 100644 --- a/Lib/Civilization.Core/Vec2i.cs +++ b/Lib/Civilization.Core/Vec2i.cs @@ -7,6 +7,9 @@ public readonly struct Vec2I(int x, int y) : IEquatable public static Vec2I operator +(Vec2I a, Vec2I b) => new(a.X + b.X, a.Y + b.Y); public static Vec2I operator -(Vec2I a, Vec2I b) => new(a.X - b.X, a.Y - b.Y); + + public static bool operator ==(Vec2I left, Vec2I right) => left.Equals(right); + public static bool operator !=(Vec2I left, Vec2I right) => !left.Equals(right); public override string ToString() => $"({X}, {Y})"; public bool Equals(Vec2I other) => X == other.X && Y == other.Y; diff --git a/global.json b/global.json new file mode 100644 index 0000000..5ce8495 --- /dev/null +++ b/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version": "8.0.100" + } +} diff --git a/godot_game/Civilization.GodotIntegration/CityRenderer.cs b/godot_game/Civilization.GodotIntegration/CityRenderer.cs index bc3526d..7e6114f 100644 --- a/godot_game/Civilization.GodotIntegration/CityRenderer.cs +++ b/godot_game/Civilization.GodotIntegration/CityRenderer.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Civilization.Core.Game; +using Civilization.GodotIntegration.Utils; using Godot; namespace Civilization.GodotIntegration; @@ -20,7 +21,7 @@ public partial class CityRenderer : Node2D foreach (var city in state.Cities) { var cityNode = CityScene.Instantiate(); - cityNode.Position = MapRenderer.MapToWorld(city.Position); + cityNode.Position = MapRenderer.MapToWorld(city.Position.ToGodot()); AddChild(cityNode); _cityViews[city.Id] = cityNode; } diff --git a/godot_game/Civilization.GodotIntegration/Civilization.GodotIntegration.csproj b/godot_game/Civilization.GodotIntegration/Civilization.GodotIntegration.csproj index 9138b10..41f30e4 100644 --- a/godot_game/Civilization.GodotIntegration/Civilization.GodotIntegration.csproj +++ b/godot_game/Civilization.GodotIntegration/Civilization.GodotIntegration.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -9,5 +9,4 @@ - diff --git a/godot_game/Civilization.GodotIntegration/GameController.cs b/godot_game/Civilization.GodotIntegration/GameController.cs index 993d8e2..dcf010a 100644 --- a/godot_game/Civilization.GodotIntegration/GameController.cs +++ b/godot_game/Civilization.GodotIntegration/GameController.cs @@ -3,6 +3,7 @@ using Civilization.Core; using Civilization.Core.Game; using Civilization.Core.Grid; using Civilization.Core.Units; +using Civilization.GodotIntegration.Utils; using Godot; namespace Civilization.GodotIntegration; @@ -26,8 +27,8 @@ public partial class GameController : Node var players = new List { - new Player(0, "Player 1", Colors.Red), - new Player(1, "Player 2", Colors.Blue) + new Player(0, "Player 1", Colors.Red.ToCore()), + new Player(1, "Player 2", Colors.Blue.ToCore()) }; var gameState = new GameState(gameMap, players); @@ -38,7 +39,7 @@ public partial class GameController : Node InputSystem.OnStateChanged = Redraw; // Add one settler to start - var settler = new Unit(0, UnitType.Settler, new Vector2I(2, 2)); + var settler = new Unit(0, UnitType.Settler, new Vector2I(2, 2).ToCore()); gameState.AddUnit(settler); GD.Print($"Added settler unit at {settler.Position}"); diff --git a/godot_game/Civilization.GodotIntegration/InputSystem.cs b/godot_game/Civilization.GodotIntegration/InputSystem.cs index 2ac534f..aa4df4e 100644 --- a/godot_game/Civilization.GodotIntegration/InputSystem.cs +++ b/godot_game/Civilization.GodotIntegration/InputSystem.cs @@ -1,5 +1,6 @@ using System; using Civilization.Core.Actions; +using Civilization.GodotIntegration.Utils; using Godot; namespace Civilization.GodotIntegration; @@ -31,7 +32,7 @@ public partial class InputSystem : Node if (selected != null) { if (!isRightClick) return; - var move = new MoveUnitAction(selected.Id, position); + var move = new MoveUnitAction(selected.Id, position.ToCore()); if (!move.CanExecute(context)) return; diff --git a/godot_game/Civilization.GodotIntegration/MapRenderer.cs b/godot_game/Civilization.GodotIntegration/MapRenderer.cs index b8f846e..2494d94 100644 --- a/godot_game/Civilization.GodotIntegration/MapRenderer.cs +++ b/godot_game/Civilization.GodotIntegration/MapRenderer.cs @@ -1,4 +1,5 @@ using Civilization.Core; +using Civilization.GodotIntegration.Utils; using Godot; namespace Civilization.GodotIntegration; @@ -33,7 +34,7 @@ public partial class MapRenderer : Node2D var pos = tile.Position; var tileId = (int)tile.Type + TileIndexOffset; var atlasCoords = tileSetSource.GetTileId(tileId); - TileMapLayer.SetCell(pos, tileId, atlasCoords); + TileMapLayer.SetCell(pos.ToGodot(), tileId, atlasCoords); } } diff --git a/godot_game/Civilization.GodotIntegration/SelectedUnitPanel.cs b/godot_game/Civilization.GodotIntegration/SelectedUnitPanel.cs index c87cb57..73e581e 100644 --- a/godot_game/Civilization.GodotIntegration/SelectedUnitPanel.cs +++ b/godot_game/Civilization.GodotIntegration/SelectedUnitPanel.cs @@ -6,21 +6,21 @@ namespace Civilization.GodotIntegration; public partial class SelectedUnitPanel : Control { - [Export] public Label UnitInfoLabel; - [Export] public Button SettleButton; - - public Action? OnSettleClicked; + // [Export] public Label UnitInfoLabel; + // [Export] public Button SettleButton; + // + // public Action? OnSettleClicked; public override void _Ready() { - SettleButton.Pressed += () => OnSettleClicked?.Invoke(); + // SettleButton.Pressed += () => OnSettleClicked?.Invoke(); Hide(); } public void ShowFor(Unit unit) { GD.Print($"Showing unit panel for {unit.Id} at {unit.Position} ({unit.Type})"); - UnitInfoLabel.Text = $"{unit.Type} at {unit.Position} ({unit.ActionPoints} AP)"; + // UnitInfoLabel.Text = $"{unit.Type} at {unit.Position} ({unit.ActionPoints} AP)"; Show(); } diff --git a/godot_game/Civilization.GodotIntegration/SelectionSystem.cs b/godot_game/Civilization.GodotIntegration/SelectionSystem.cs index 5a9adcb..994459c 100644 --- a/godot_game/Civilization.GodotIntegration/SelectionSystem.cs +++ b/godot_game/Civilization.GodotIntegration/SelectionSystem.cs @@ -1,6 +1,7 @@ using System.Linq; using Civilization.Core.Game; using Civilization.Core.Units; +using Civilization.GodotIntegration.Utils; using Godot; namespace Civilization.GodotIntegration; @@ -13,7 +14,8 @@ public partial class SelectionSystem : Node2D public bool TrySelectUnitAt(Vector2I tilePos, GameState state) { - var unit = state.GetUnitsForPlayer(state.CurrentPlayer.Id).FirstOrDefault(u => u.Position == tilePos); + var coreTilePos = tilePos.ToCore(); + var unit = state.GetUnitsForPlayer(state.CurrentPlayer.Id).FirstOrDefault(u => u.Position == coreTilePos); if (unit == null) return false; SelectedUnit = unit; diff --git a/godot_game/Civilization.GodotIntegration/UiController.cs b/godot_game/Civilization.GodotIntegration/UiController.cs index 1e8f2d1..dd941f8 100644 --- a/godot_game/Civilization.GodotIntegration/UiController.cs +++ b/godot_game/Civilization.GodotIntegration/UiController.cs @@ -14,7 +14,7 @@ public partial class UiController : Node public override void _Ready() { - UnitPanel.OnSettleClicked = TrySettleCity; + // UnitPanel.OnSettleClicked = TrySettleCity; } public override void _Process(double delta) diff --git a/godot_game/Civilization.GodotIntegration/UnitRenderer.cs b/godot_game/Civilization.GodotIntegration/UnitRenderer.cs index 0dce364..7c8120f 100644 --- a/godot_game/Civilization.GodotIntegration/UnitRenderer.cs +++ b/godot_game/Civilization.GodotIntegration/UnitRenderer.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Civilization.Core.Game; +using Civilization.GodotIntegration.Utils; using Godot; namespace Civilization.GodotIntegration; @@ -20,7 +21,7 @@ public partial class UnitRenderer : Node2D foreach (var unit in state.Units) { var unitNode = UnitScene.Instantiate(); - unitNode.Position = MapRenderer.MapToWorld(unit.Position); + unitNode.Position = MapRenderer.MapToWorld(unit.Position.ToGodot()); AddChild(unitNode); _unitViews[unit.Id] = unitNode; } diff --git a/godot_game/Civilization.GodotIntegration/Utils/GodotConversionExtensions.cs b/godot_game/Civilization.GodotIntegration/Utils/GodotConversionExtensions.cs new file mode 100644 index 0000000..67003d7 --- /dev/null +++ b/godot_game/Civilization.GodotIntegration/Utils/GodotConversionExtensions.cs @@ -0,0 +1,13 @@ +using Civilization.Core; +using Godot; + +namespace Civilization.GodotIntegration.Utils; + +public static class GodotConversionExtensions +{ + public static Vector2I ToGodot(this Vec2I v) => new(v.X, v.Y); + public static Vec2I ToCore(this Vector2I v) => new(v.X, v.Y); + + public static Color ToGodot(this ColorRGBA c) => new(c.R / 255f, c.G / 255f, c.B / 255f, c.A / 255f); + public static ColorRGBA ToCore(this Color c) => new((byte)(c.R * 255), (byte)(c.G * 255), (byte)(c.B * 255), (byte)(c.A * 255)); +} \ No newline at end of file diff --git a/godot_game/Scenes/world.tscn b/godot_game/Scenes/world.tscn index 7dff351..e560ae7 100644 --- a/godot_game/Scenes/world.tscn +++ b/godot_game/Scenes/world.tscn @@ -27,8 +27,8 @@ tile_map_data = PackedByteArray("AADj/+j/AQAAAAAAAADj/+n/AQAAAAAAAADj/+r/AQAAAAA [node name="MapRenderer" type="Node2D" parent="." node_paths=PackedStringArray("TileMapLayer")] script = ExtResource("2_5a7ea") -TileMapLayer = NodePath("../TileMapLayer") TileSet = ExtResource("2_8j60k") +TileMapLayer = NodePath("../TileMapLayer") [node name="Camera2D" type="Camera2D" parent="."] zoom = Vector2(30, 30) @@ -64,6 +64,7 @@ text = "End turn" offset_top = 482.0 offset_right = -480.0 offset_bottom = 1.0 +script = null [node name="UIController" type="Node" parent="." node_paths=PackedStringArray("TurnLabel", "UnitPanel", "StateProvider", "SelectionSystem", "GameController")] script = ExtResource("6_5ukr8") diff --git a/godot_game/UI/selected_unit_panel.tscn b/godot_game/UI/selected_unit_panel.tscn index 99d4ded..d6352d9 100644 --- a/godot_game/UI/selected_unit_panel.tscn +++ b/godot_game/UI/selected_unit_panel.tscn @@ -1,8 +1,8 @@ [gd_scene load_steps=2 format=3 uid="uid://na1o6j7stseb"] -[ext_resource type="Script" uid="uid://c3mt3skudb7ky" path="res://GodotIntegration/SelectedUnitPanel.cs" id="1_sosfk"] +[ext_resource type="Script" uid="uid://qqlmdir1bdjd" path="res://Civilization.GodotIntegration/SelectedUnitPanel.cs" id="1_sosfk"] -[node name="SelectedUnitPanel" type="MarginContainer" node_paths=PackedStringArray("UnitInfoLabel", "SettleButton")] +[node name="SelectedUnitPanel" type="MarginContainer"] anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 @@ -13,8 +13,6 @@ theme_override_constants/margin_top = 8 theme_override_constants/margin_right = 8 theme_override_constants/margin_bottom = 8 script = ExtResource("1_sosfk") -UnitInfoLabel = NodePath("UnitInfoLabel") -SettleButton = NodePath("SettleButton") [node name="UnitInfoLabel" type="Label" parent="."] layout_mode = 2 diff --git a/godot_game/project.godot b/godot_game/project.godot index 0fcd36d..b41f717 100644 --- a/godot_game/project.godot +++ b/godot_game/project.godot @@ -17,7 +17,8 @@ config/icon="res://icon.svg" [dotnet] -project/assembly_name="civilization" +project/assembly_name="Civilization.GodotIntegration" +project/solution_directory="res://../" [rendering]