diff --git a/half-earth/materials/tile.tres b/half-earth/materials/tile.tres index 9f921a3..5d91ee6 100644 --- a/half-earth/materials/tile.tres +++ b/half-earth/materials/tile.tres @@ -5,6 +5,6 @@ [resource] resource_local_to_scene = true shader = ExtResource( 1 ) -shader_param/lowColor = Color( 0.0313726, 0, 1, 1 ) -shader_param/highColor = Color( 1, 0, 0, 1 ) +shader_param/lowColor = Color( 0, 0, 0, 1 ) +shader_param/highColor = Color( 1, 0.560784, 0, 1 ) shader_param/t = null diff --git a/half-earth/nodes/game.tscn b/half-earth/nodes/game.tscn index 1cf51a8..a23d717 100644 --- a/half-earth/nodes/game.tscn +++ b/half-earth/nodes/game.tscn @@ -16,4 +16,5 @@ Grid = NodePath("../Grid") [node name="Clock" parent="." instance=ExtResource( 4 )] +[connection signal="OnTick" from="Clock" to="Grid" method="_on_Clock_OnTick"] [connection signal="OnTick" from="Clock" to="Debug UI" method="_on_Clock_OnTick"] diff --git a/half-earth/scripts/GridCursor.cs b/half-earth/scripts/GridCursor.cs index 6ff61a0..c2f1631 100644 --- a/half-earth/scripts/GridCursor.cs +++ b/half-earth/scripts/GridCursor.cs @@ -15,11 +15,11 @@ public class GridCursor : Sprite _grid = GetNode(Grid); _material = (ShaderMaterial)Material; } - + public override void _Input(InputEvent @event) { base._Input(@event); - + if (@event is InputEventMouseMotion mouseMoveEvent) { var pos = mouseMoveEvent.Position; @@ -37,7 +37,7 @@ public class GridCursor : Sprite { var pos = mouseButtonEvent.Position; _grid.GetGridPos(pos, out var x, out var y); - _grid.ToggleTileHighlight(x, y); + _grid.SetTileValue(x, y, 1.0f); _material.SetShaderParam(T, 1f); } else diff --git a/half-earth/scripts/WorldGrid.cs b/half-earth/scripts/WorldGrid.cs index 8a69681..45e7e2b 100644 --- a/half-earth/scripts/WorldGrid.cs +++ b/half-earth/scripts/WorldGrid.cs @@ -8,11 +8,15 @@ public class WorldGrid : Node2D [Export] public int Size { get; set; } - + [Export] public int CellSize { get; set; } - + + [Export] + public float DiffusionCoefficient { get; set; } = 0.01f; + private Tile[,] _tiles; + private float[,] _nextValues = null; // Called when the node enters the scene tree for the first time. public override void _Ready() @@ -23,18 +27,18 @@ public class WorldGrid : Node2D public override void _Process(float delta) { base._Process(delta); - + for (int x = 0; x < Size; x++) { for (int y = 0; y < Size; y++) { var tile = _tiles[x, y]; var material = tile.material; - material.SetShaderParam("t", tile.isHighlighted ? 1f : 0f); + material.SetShaderParam("t", tile.value); } } } - + public bool IsInBounds(int x, int y) { return x >= 0 && x < Size && y >= 0 && y < Size; @@ -47,7 +51,7 @@ public class WorldGrid : Node2D _tiles[x, y].isHighlighted ^= true; } - + public void SetTileValue(int x, int y, float value) { _tiles[x, y].value = value; @@ -75,8 +79,9 @@ public class WorldGrid : Node2D private void GenerateGrid(int size) { this.Clear(); - + _tiles = new Tile[size, size]; + _nextValues = new float[size, size]; for (int x = 0; x < size; x++) { @@ -85,7 +90,7 @@ public class WorldGrid : Node2D var tile = new Tile(); tile.isHighlighted = false; tile.value = 0.0f; - + var node = TileScene.Instance(); this.AddChild(node); var position = new Vector2 @@ -96,9 +101,63 @@ public class WorldGrid : Node2D node.Position = position; var canvasItem = (CanvasItem)node; tile.material = (ShaderMaterial)canvasItem.Material; - + _tiles[x, y] = tile; } } } + + public void _on_Clock_OnTick(int ticks) + { + Diffuse(); + } + + private float TransferHeat(float t0, float alpha, float nx, float ny, float px, float py) + { + float d2tdx2 = nx - 2 * t0 + px; + float d2tdy2 = ny - 2 * t0 + py; + return t0 + alpha * (d2tdx2 + d2tdy2); + } + + 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].value; + + nx = x > 0 ? _tiles[x - 1, y].value : t; + px = x < Size - 1 ? _tiles[x + 1, y].value : t; + + ny = y > 0 ? _tiles[x, y - 1].value : t; + py = y < Size - 1 ? _tiles[x, y + 1].value : t; + } + + private void Diffuse() + { + for (int x = 0; x < Size; x++) + { + for (int y = 0; y < Size; y++) + { + float t = _tiles[x, y].value; + var D = DiffusionCoefficient; + + GetNeighbourTemperatures( + x, y, + out var nx, + out var ny, + out var px, + out var py); + + // current value + _nextValues[x, y] = TransferHeat(t, D, nx, ny, px, py); + } + } + + for (int x = 0; x < Size; x++) + { + for (int y = 0; y < Size; y++) + { + _tiles[x, y].value = _nextValues[x, y]; + } + } + } }