extract logical tile grid to resource #6
This commit is contained in:
		
							parent
							
								
									006510956c
								
							
						
					
					
						commit
						09b7457e71
					
				| @ -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") | ||||
|  | ||||
| @ -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 ) | ||||
|  | ||||
| @ -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 | ||||
| @ -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 ) | ||||
							
								
								
									
										9
									
								
								half-earth/resources/tiles/tiles.tres
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								half-earth/resources/tiles/tiles.tres
									
									
									
									
									
										Normal file
									
								
							| @ -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 ) | ||||
| @ -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<Node2D>(); | ||||
|             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<Node2D>(); | ||||
|                 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 | ||||
| } | ||||
|  | ||||
| @ -4,6 +4,5 @@ public struct Tile | ||||
| { | ||||
|     public bool isHighlighted; | ||||
|     public float temperature; | ||||
|     public ShaderMaterial material; | ||||
|     public TileType type; | ||||
| } | ||||
							
								
								
									
										92
									
								
								half-earth/scripts/tile/TileGrid.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								half-earth/scripts/tile/TileGrid.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,92 @@ | ||||
| using Godot; | ||||
| using System; | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| public class TileGrid : Resource, IReadOnlyList<Tile> | ||||
| { | ||||
|     [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<Tile> Tiles | ||||
|     { | ||||
|         get | ||||
|         { | ||||
|             if (_tiles == null) | ||||
|             { | ||||
|                 _tiles = new List<Tile>(); | ||||
|                 Generate(_tiles); | ||||
|             } | ||||
| 
 | ||||
|             return _tiles; | ||||
|         } | ||||
|     } | ||||
|     private List<Tile> _tiles = null; | ||||
| 
 | ||||
|     private void Generate(List<Tile> 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<Tile> 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; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user