From 09b7457e71e776980ed9b07a9f4687ee3099ae55 Mon Sep 17 00:00:00 2001 From: Cat Flynn Date: Sat, 10 Dec 2022 15:47:44 +0000 Subject: [PATCH] extract logical tile grid to resource #6 --- half-earth/nodes/game.tscn | 4 +- .../nodes/interaction_modes/build_mode.tscn | 2 +- .../{ => tiles}/tile_types/developed.tres | 2 +- .../buildable_tiles.tres | 2 +- .../{ => tiles}/tile_types/wild.tres | 0 half-earth/resources/tiles/tiles.tres | 9 + half-earth/scripts/WorldGrid.cs | 190 +++++++++--------- half-earth/scripts/tile/Tile.cs | 1 - half-earth/scripts/tile/TileGrid.cs | 92 +++++++++ 9 files changed, 198 insertions(+), 104 deletions(-) rename half-earth/resources/{ => tiles}/tile_types/developed.tres (92%) rename half-earth/resources/{ => tiles}/tile_types/tile_type_collections/buildable_tiles.tres (70%) rename half-earth/resources/{ => tiles}/tile_types/wild.tres (100%) create mode 100644 half-earth/resources/tiles/tiles.tres create mode 100644 half-earth/scripts/tile/TileGrid.cs diff --git a/half-earth/nodes/game.tscn b/half-earth/nodes/game.tscn index 40b7b54..c86e8f4 100644 --- a/half-earth/nodes/game.tscn +++ b/half-earth/nodes/game.tscn @@ -7,7 +7,7 @@ [ext_resource path="res://nodes/interaction_modes/interaction_mode.tscn" type="PackedScene" id=5] [ext_resource path="res://nodes/ui/build_mode_ui.tscn" type="PackedScene" id=6] [ext_resource path="res://nodes/interaction_modes/build_mode.tscn" type="PackedScene" id=7] -[ext_resource path="res://resources/tile_types/wild.tres" type="Resource" id=8] +[ext_resource path="res://resources/tiles/tiles.tres" type="Resource" id=8] [ext_resource path="res://nodes/ui/mode_selection_ui.tscn" type="PackedScene" id=9] [sub_resource type="Curve" id=1] @@ -20,7 +20,7 @@ _autoTick = true [node name="Grid" parent="." instance=ExtResource( 1 )] DiffusionCoefficient = 0.1 -_startTileTypeResource = ExtResource( 8 ) +_tileGridResource = ExtResource( 8 ) [node name="Cursor" parent="." instance=ExtResource( 2 )] Grid = NodePath("../Grid") diff --git a/half-earth/nodes/interaction_modes/build_mode.tscn b/half-earth/nodes/interaction_modes/build_mode.tscn index 4c2ca0e..c3f0f36 100644 --- a/half-earth/nodes/interaction_modes/build_mode.tscn +++ b/half-earth/nodes/interaction_modes/build_mode.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=3 format=2] [ext_resource path="res://scripts/interaction_modes/BuildMode.cs" type="Script" id=1] -[ext_resource path="res://resources/tile_types/tile_type_collections/buildable_tiles.tres" type="Resource" id=2] +[ext_resource path="res://resources/tiles/tile_types/tile_type_collections/buildable_tiles.tres" type="Resource" id=2] [node name="Build Mode" type="Node"] script = ExtResource( 1 ) diff --git a/half-earth/resources/tile_types/developed.tres b/half-earth/resources/tiles/tile_types/developed.tres similarity index 92% rename from half-earth/resources/tile_types/developed.tres rename to half-earth/resources/tiles/tile_types/developed.tres index 70a9358..1efdccf 100644 --- a/half-earth/resources/tile_types/developed.tres +++ b/half-earth/resources/tiles/tile_types/developed.tres @@ -8,4 +8,4 @@ Name = "Developed" BuildLabel = "[D]eveloped" Key = 68 Color = Color( 0.372549, 0.372549, 0.372549, 1 ) -HeatGeneration = 0.1 +HeatGeneration = 0.5 diff --git a/half-earth/resources/tile_types/tile_type_collections/buildable_tiles.tres b/half-earth/resources/tiles/tile_types/tile_type_collections/buildable_tiles.tres similarity index 70% rename from half-earth/resources/tile_types/tile_type_collections/buildable_tiles.tres rename to half-earth/resources/tiles/tile_types/tile_type_collections/buildable_tiles.tres index 5a046c8..b8d9f13 100644 --- a/half-earth/resources/tile_types/tile_type_collections/buildable_tiles.tres +++ b/half-earth/resources/tiles/tile_types/tile_type_collections/buildable_tiles.tres @@ -1,7 +1,7 @@ [gd_resource type="Resource" load_steps=3 format=2] [ext_resource path="res://scripts/tile/TileTypeCollection.cs" type="Script" id=1] -[ext_resource path="res://resources/tile_types/developed.tres" type="Resource" id=2] +[ext_resource path="res://resources/tiles/tile_types/developed.tres" type="Resource" id=2] [resource] script = ExtResource( 1 ) diff --git a/half-earth/resources/tile_types/wild.tres b/half-earth/resources/tiles/tile_types/wild.tres similarity index 100% rename from half-earth/resources/tile_types/wild.tres rename to half-earth/resources/tiles/tile_types/wild.tres diff --git a/half-earth/resources/tiles/tiles.tres b/half-earth/resources/tiles/tiles.tres new file mode 100644 index 0000000..288c93f --- /dev/null +++ b/half-earth/resources/tiles/tiles.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" load_steps=3 format=2] + +[ext_resource path="res://scripts/tile/TileGrid.cs" type="Script" id=1] +[ext_resource path="res://resources/tiles/tile_types/wild.tres" type="Resource" id=2] + +[resource] +script = ExtResource( 1 ) +Size = 10 +_startTileTypeResource = ExtResource( 2 ) diff --git a/half-earth/scripts/WorldGrid.cs b/half-earth/scripts/WorldGrid.cs index d454cb3..6083638 100644 --- a/half-earth/scripts/WorldGrid.cs +++ b/half-earth/scripts/WorldGrid.cs @@ -7,11 +7,8 @@ public class WorldGrid : Node2D private PackedScene TileScene { get; set; } [Export] - private Resource _startTileTypeResource; - private TileType _startTileType; - - [Export] - public int Size { get; set; } + private Resource _tileGridResource; + private TileGrid _tileGrid; [Export] public int CellSize { get; set; } @@ -19,65 +16,65 @@ public class WorldGrid : Node2D [Export] public float DiffusionCoefficient { get; set; } = 0.01f; - private Tile[,] _tiles; - private float[,] _nextValues = null; + private float[] _nextValues = null; + + private struct TileView + { + public ShaderMaterial material; + } + private TileView[] _tileViews; // Called when the node enters the scene tree for the first time. public override void _Ready() { - _startTileType = (TileType)_startTileTypeResource; + _tileGrid = (TileGrid)_tileGridResource; - GenerateGrid(Size); + GenerateCanvasItems(_tileGrid); } public override void _Process(float delta) { base._Process(delta); - for (int x = 0; x < Size; x++) + // TODO: this is a rendering concern that should be performed + // by the heat overlay + for (int i = 0; i < _tileGrid.Count; i++) { - for (int y = 0; y < Size; y++) - { - var tile = _tiles[x, y]; - var material = tile.material; - material.SetShaderParam("t", tile.temperature); - } + var tile = _tileGrid[i]; + var view = _tileViews[i]; + + view.material.SetShaderParam("t", tile.temperature); } } - public bool IsInBounds(int x, int y) - { - return x >= 0 && x < Size && y >= 0 && y < Size; - } - - public void ToggleTileHighlight(int x, int y) - { - if (!IsInBounds(x, y)) - return; - - _tiles[x, y].isHighlighted ^= true; - } - - public void SetTileType(int x, int y, TileType tileType) - { - if (!IsInBounds(x, y)) - return; - - GD.Print($"set ({x}, {y}) to {tileType}"); - _tiles[x, y].type = tileType; - _tiles[x, y].material.SetShaderParam("lowColor", tileType.Color); - } - + #region Positioning public void GetGridPos(Vector2 position, out int x, out int y) { x = Mathf.FloorToInt(position.x / CellSize); y = Mathf.FloorToInt(position.y / CellSize); } + public bool IsInBounds(int x, int y) => _tileGrid.IsInBounds(x, y); + #endregion + + #region Interaction + public void SetTileType(int x, int y, TileType tileType) + { + if (!_tileGrid.IsInBounds(x, y)) + return; + + _tileGrid.MapPosition(x, y, out var idx); + + var tile = _tileGrid[idx]; + tile.type = tileType; + _tileGrid[x, y] = tile; + + _tileViews[idx].material.SetShaderParam("lowColor", tileType.Color); + } + #endregion + private void Clear() { - _tiles = null; - int children = this.GetChildCount(); GD.Print(children); for (int i = 0; i < children; i++) @@ -85,38 +82,37 @@ public class WorldGrid : Node2D var child = this.GetChild(i); child.QueueFree(); } + + _tileViews = null; } - private void GenerateGrid(int size) + private void GenerateCanvasItems(TileGrid grid) { this.Clear(); - _tiles = new Tile[size, size]; - _nextValues = new float[size, size]; + _tileViews = new TileView[grid.Count]; + _nextValues = new float[grid.Count]; - for (int x = 0; x < size; x++) + for (int i = 0; i < grid.Count; i++) { - for (int y = 0; y < size; y++) + _tileGrid.MapIndex(i, out var x, out var y); + + var node = TileScene.Instance(); + this.AddChild(node); + var position = new Vector2 { - var tile = new Tile(); - tile.isHighlighted = false; - tile.temperature = 0.0f; - tile.type = _startTileType; + x = (x + .5f) * CellSize, + y = (y + .5f) * CellSize + }; + node.Position = position; + var canvasItem = (CanvasItem)node; - var node = TileScene.Instance(); - this.AddChild(node); - var position = new Vector2 - { - x = (x + .5f) * CellSize, - y = (y + .5f) * CellSize - }; - node.Position = position; - var canvasItem = (CanvasItem)node; - tile.material = (ShaderMaterial)canvasItem.Material; - tile.material.SetShaderParam("lowColor", _startTileType.Color); + var tile = _tileGrid[i]; - _tiles[x, y] = tile; - } + TileView view = default; + view.material = (ShaderMaterial)canvasItem.Material; + view.material.SetShaderParam("lowColor", _tileGrid.StartTileType.Color); + _tileViews[i] = view; } } @@ -126,6 +122,7 @@ public class WorldGrid : Node2D Diffuse(); } + #region Simulation private float TransferHeat(float t0, float alpha, float nx, float ny, float px, float py) { float d2tdx2 = nx - 2 * t0 + px; @@ -136,59 +133,56 @@ public class WorldGrid : Node2D private void GetNeighbourTemperatures(int x, int y, out float nx, out float ny, out float px, out float py) { // default value - var t = _tiles[x, y].temperature; + var t = _tileGrid[x, y].temperature; - nx = x > 0 ? _tiles[x - 1, y].temperature : t; - px = x < Size - 1 ? _tiles[x + 1, y].temperature : t; + nx = x > 0 ? _tileGrid[x - 1, y].temperature : t; + px = x < _tileGrid.Size - 1 ? _tileGrid[x + 1, y].temperature : t; - ny = y > 0 ? _tiles[x, y - 1].temperature : t; - py = y < Size - 1 ? _tiles[x, y + 1].temperature : t; + ny = y > 0 ? _tileGrid[x, y - 1].temperature : t; + py = y < _tileGrid.Size - 1 ? _tileGrid[x, y + 1].temperature : t; } private void GenerateHeat() { - for (int x = 0; x < Size; x++) + for (int i = 0; i < _tileGrid.Count; i++) { - for (int y = 0; y < Size; y++) - { - var tile = _tiles[x, y]; - var type = tile.type; - tile.temperature += type.HeatGeneration; - _tiles[x, y] = tile; - } + var tile = _tileGrid[i]; + var type = tile.type; + tile.temperature += type.HeatGeneration; + _tileGrid[i] = tile; } } private void Diffuse() { - for (int x = 0; x < Size; x++) + var D = DiffusionCoefficient; + + for (int i = 0; i < _tileGrid.Count; i++) { - for (int y = 0; y < Size; y++) - { - float t = _tiles[x, y].temperature; - var D = DiffusionCoefficient; + float t = _tileGrid[i].temperature; - GetNeighbourTemperatures( - x, y, - out var nx, - out var ny, - out var px, - out var py); + _tileGrid.MapIndex(i, out var x, out var y); - // current value - var temperature = TransferHeat(t, D, nx, ny, px, py); - // TODO: what if it's really really cold out? - temperature = Mathf.Max(0, temperature); - _nextValues[x, y] = temperature; - } + GetNeighbourTemperatures( + x, y, + out var nx, + out var ny, + out var px, + out var py); + + var temperature = TransferHeat(t, D, nx, ny, px, py); + + // TODO: what if it's really really cold out? + temperature = Mathf.Max(0, temperature); + _nextValues[i] = temperature; } - for (int x = 0; x < Size; x++) + for (int i = 0; i < _tileGrid.Count; i++) { - for (int y = 0; y < Size; y++) - { - _tiles[x, y].temperature = _nextValues[x, y]; - } + var tile = _tileGrid[i]; + tile.temperature = _nextValues[i]; + _tileGrid[i] = tile; } } + #endregion } diff --git a/half-earth/scripts/tile/Tile.cs b/half-earth/scripts/tile/Tile.cs index e247129..662c72c 100644 --- a/half-earth/scripts/tile/Tile.cs +++ b/half-earth/scripts/tile/Tile.cs @@ -4,6 +4,5 @@ public struct Tile { public bool isHighlighted; public float temperature; - public ShaderMaterial material; public TileType type; } \ No newline at end of file diff --git a/half-earth/scripts/tile/TileGrid.cs b/half-earth/scripts/tile/TileGrid.cs new file mode 100644 index 0000000..7a2eb08 --- /dev/null +++ b/half-earth/scripts/tile/TileGrid.cs @@ -0,0 +1,92 @@ +using Godot; +using System; +using System.Collections; +using System.Collections.Generic; + +public class TileGrid : Resource, IReadOnlyList +{ + [Export] + public int Size { get; private set; } = 10; + + [Export] + private Resource _startTileTypeResource; + public TileType StartTileType => (TileType)_startTileTypeResource; + + public int Count => Size * Size; + + public Tile this[int index] + { + get => Tiles[index]; + set => Tiles[index] = value; + } + + public Tile this[int x, int y] + { + get + { + MapPosition(x, y, out int idx); + return Tiles[idx]; + } + set + { + MapPosition(x, y, out int idx); + Tiles[idx] = value; + } + } + + private List Tiles + { + get + { + if (_tiles == null) + { + _tiles = new List(); + Generate(_tiles); + } + + return _tiles; + } + } + private List _tiles = null; + + private void Generate(List tiles) + { + tiles.Clear(); + for (int i = 0; i < Count; i++) + { + var tile = new Tile(); + tile.isHighlighted = false; + tile.temperature = 0.0f; + tile.type = StartTileType; + + tiles.Add(tile); + } + } + + public IEnumerator GetEnumerator() + { + return Tiles.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return Tiles.GetEnumerator(); + } + + public void MapIndex(int idx, out int x, out int y) + { + y = idx / Size; + x = idx % Size; + } + + public void MapPosition(int x, int y, out int idx) + { + idx = y * Size + x; + } + + public bool IsInBounds(int x, int y) + { + return x >= 0 && x < Size && y >= 0 && y < Size; + } +} +