Compare commits
	
		
			2 Commits
		
	
	
		
			main
			...
			tile-healt
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| c22827967f | |||
| 6793335983 | 
@ -4,3 +4,5 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[resource]
 | 
					[resource]
 | 
				
			||||||
script = ExtResource( 1 )
 | 
					script = ExtResource( 1 )
 | 
				
			||||||
 | 
					_healthy = Color( 0.0431373, 0.541176, 0.0235294, 1 )
 | 
				
			||||||
 | 
					_depleted = Color( 0.670588, 0.572549, 0.27451, 1 )
 | 
				
			||||||
 | 
				
			|||||||
@ -7,4 +7,4 @@ script = ExtResource( 1 )
 | 
				
			|||||||
Name = "Developed"
 | 
					Name = "Developed"
 | 
				
			||||||
Key = 68
 | 
					Key = 68
 | 
				
			||||||
Color = Color( 0.372549, 0.372549, 0.372549, 1 )
 | 
					Color = Color( 0.372549, 0.372549, 0.372549, 1 )
 | 
				
			||||||
HeatGeneration = 0.4
 | 
					HeatGeneration = 0.15
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,11 @@
 | 
				
			|||||||
[gd_resource type="Resource" load_steps=2 format=2]
 | 
					[gd_resource type="Resource" load_steps=2 format=2]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[ext_resource path="res://scripts/tile/TileType.cs" type="Script" id=1]
 | 
					[ext_resource path="res://scripts/tile/Wild.cs" type="Script" id=1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[resource]
 | 
					[resource]
 | 
				
			||||||
script = ExtResource( 1 )
 | 
					script = ExtResource( 1 )
 | 
				
			||||||
Name = "Wild"
 | 
					Name = "Wild"
 | 
				
			||||||
Key = 87
 | 
					Key = 87
 | 
				
			||||||
Color = Color( 0, 0.545098, 0.0196078, 1 )
 | 
					Color = Color( 0.14902, 1, 0, 0 )
 | 
				
			||||||
HeatGeneration = -0.2
 | 
					HeatGeneration = -0.02
 | 
				
			||||||
 | 
					Threshold = 0.6
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										100
									
								
								half-earth/scripts/HeatSystem.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								half-earth/scripts/HeatSystem.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,100 @@
 | 
				
			|||||||
 | 
					using Godot;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class HeatSystem
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private readonly TileGrid _tiles;
 | 
				
			||||||
 | 
					    private readonly float _diffusionCoefficient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private float[] _nextTemperatures = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public HeatSystem(TileGrid tiles, float diffusionCoefficient)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        _tiles = tiles;
 | 
				
			||||||
 | 
					        _diffusionCoefficient = diffusionCoefficient;
 | 
				
			||||||
 | 
					        _nextTemperatures = new float[tiles.Count];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void Process()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        GenerateHeat();
 | 
				
			||||||
 | 
					        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].temperature;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        nx = x > 0 ? _tiles[x - 1, y].temperature : t;
 | 
				
			||||||
 | 
					        px = x < _tiles.Size - 1 ? _tiles[x + 1, y].temperature : t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ny = y > 0 ? _tiles[x, y - 1].temperature : t;
 | 
				
			||||||
 | 
					        py = y < _tiles.Size - 1 ? _tiles[x, y + 1].temperature : t;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    private void GenerateHeat()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        for (int i = 0; i < _tiles.Count; i++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var tile = _tiles[i];
 | 
				
			||||||
 | 
					            var type = tile.type;
 | 
				
			||||||
 | 
					            tile.temperature += type.HeatGeneration;
 | 
				
			||||||
 | 
					            ApplyHeatDamage(ref tile);
 | 
				
			||||||
 | 
					            _tiles[i] = tile;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void ApplyHeatDamage(ref Tile tile)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!(tile.type is IDamageable damageable))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var surplus = tile.temperature - damageable.Threshold;
 | 
				
			||||||
 | 
					        if (surplus < 0)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // TODO: parameterised balancing
 | 
				
			||||||
 | 
					        tile.currentHealth -= surplus;
 | 
				
			||||||
 | 
					        tile.currentHealth = Mathf.Clamp(tile.currentHealth, 0, 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void Diffuse()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var D = _diffusionCoefficient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (int i = 0; i < _tiles.Count; i++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            float t = _tiles[i].temperature;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _tiles.MapIndex(i, out var x, out var y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            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);
 | 
				
			||||||
 | 
					            _nextTemperatures[i] = temperature;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (int i = 0; i < _tiles.Count; i++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var tile = _tiles[i];
 | 
				
			||||||
 | 
					            tile.temperature = _nextTemperatures[i];
 | 
				
			||||||
 | 
					            _tiles[i] = tile;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -16,13 +16,12 @@ public class WorldGrid : Node2D
 | 
				
			|||||||
    [Export]
 | 
					    [Export]
 | 
				
			||||||
    public float DiffusionCoefficient { get; set; } = 0.01f;
 | 
					    public float DiffusionCoefficient { get; set; } = 0.01f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private float[] _nextValues = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public struct TileView
 | 
					    public struct TileView
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public ShaderMaterial material;
 | 
					        public ShaderMaterial material;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    private TileView[] _tileViews;
 | 
					    private TileView[] _tileViews;
 | 
				
			||||||
 | 
					    private HeatSystem _heat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Called when the node enters the scene tree for the first time.
 | 
					    // Called when the node enters the scene tree for the first time.
 | 
				
			||||||
    public override void _Ready()
 | 
					    public override void _Ready()
 | 
				
			||||||
@ -30,6 +29,8 @@ public class WorldGrid : Node2D
 | 
				
			|||||||
        _tileGrid = (TileGrid)_tileGridResource;
 | 
					        _tileGrid = (TileGrid)_tileGridResource;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        GenerateCanvasItems(_tileGrid);
 | 
					        GenerateCanvasItems(_tileGrid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _heat = new HeatSystem(_tileGrid, DiffusionCoefficient);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #region Positioning
 | 
					    #region Positioning
 | 
				
			||||||
@ -53,8 +54,6 @@ public class WorldGrid : Node2D
 | 
				
			|||||||
        var tile = _tileGrid[idx];
 | 
					        var tile = _tileGrid[idx];
 | 
				
			||||||
        tile.type = tileType;
 | 
					        tile.type = tileType;
 | 
				
			||||||
        _tileGrid[x, y] = tile;
 | 
					        _tileGrid[x, y] = tile;
 | 
				
			||||||
 | 
					 | 
				
			||||||
        _tileViews[idx].material.SetShaderParam("lowColor", tileType.Color);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    #endregion
 | 
					    #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -76,7 +75,6 @@ public class WorldGrid : Node2D
 | 
				
			|||||||
        this.Clear();
 | 
					        this.Clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        _tileViews = new TileView[grid.Count];
 | 
					        _tileViews = new TileView[grid.Count];
 | 
				
			||||||
        _nextValues = new float[grid.Count];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (int i = 0; i < grid.Count; i++)
 | 
					        for (int i = 0; i < grid.Count; i++)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -96,80 +94,11 @@ public class WorldGrid : Node2D
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            TileView view = default;
 | 
					            TileView view = default;
 | 
				
			||||||
            view.material = (ShaderMaterial)canvasItem.Material;
 | 
					            view.material = (ShaderMaterial)canvasItem.Material;
 | 
				
			||||||
            view.material.SetShaderParam("lowColor", _tileGrid.StartTileType.Color);
 | 
					 | 
				
			||||||
            _tileViews[i] = view;
 | 
					            _tileViews[i] = view;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public ShaderMaterial GetTileMaterial(int idx) => _tileViews[idx].material;
 | 
					    public ShaderMaterial GetTileMaterial(int idx) => _tileViews[idx].material;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #region Simulation
 | 
					    public void _on_Clock_OnTick(int ticks) => _heat.Process();
 | 
				
			||||||
    public void _on_Clock_OnTick(int ticks)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        GenerateHeat();
 | 
					 | 
				
			||||||
        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 = _tileGrid[x, y].temperature;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        nx = x > 0 ? _tileGrid[x - 1, y].temperature : t;
 | 
					 | 
				
			||||||
        px = x < _tileGrid.Size - 1 ? _tileGrid[x + 1, y].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 i = 0; i < _tileGrid.Count; i++)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            var tile = _tileGrid[i];
 | 
					 | 
				
			||||||
            var type = tile.type;
 | 
					 | 
				
			||||||
            tile.temperature += type.HeatGeneration;
 | 
					 | 
				
			||||||
            _tileGrid[i] = tile;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private void Diffuse()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        var D = DiffusionCoefficient;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (int i = 0; i < _tileGrid.Count; i++)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            float t = _tileGrid[i].temperature;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            _tileGrid.MapIndex(i, out var x, out var y);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            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 i = 0; i < _tileGrid.Count; i++)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            var tile = _tileGrid[i];
 | 
					 | 
				
			||||||
            tile.temperature = _nextValues[i];
 | 
					 | 
				
			||||||
            _tileGrid[i] = tile;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    #endregion
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -2,10 +2,25 @@ using Godot;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
public class NoOverlay : Overlay
 | 
					public class NoOverlay : Overlay
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    [Export]
 | 
				
			||||||
 | 
					    private Color _healthy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [Export]
 | 
				
			||||||
 | 
					    private Color _depleted;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // in this view we want to draw tiles with their normal colour
 | 
					    // in this view we want to draw tiles with their normal colour
 | 
				
			||||||
    public override void Apply(Tile tile, ShaderMaterial material)
 | 
					    public override void Apply(Tile tile, ShaderMaterial material)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        var type = tile.type;
 | 
					        var type = tile.type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (type is Wild wild)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            material.SetShaderParam("lowColor", _depleted);
 | 
				
			||||||
 | 
					            material.SetShaderParam("highColor", _healthy);
 | 
				
			||||||
 | 
					            material.SetShaderParam("t", tile.currentHealth);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        material.SetShaderParam("lowColor", type.Color);
 | 
					        material.SetShaderParam("lowColor", type.Color);
 | 
				
			||||||
        material.SetShaderParam("t", 0);
 | 
					        material.SetShaderParam("t", 0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								half-earth/scripts/tile/IDamageable.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								half-earth/scripts/tile/IDamageable.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					public interface IDamageable
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    float Threshold { get; }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -5,4 +5,5 @@ public struct Tile
 | 
				
			|||||||
    public bool isHighlighted;
 | 
					    public bool isHighlighted;
 | 
				
			||||||
    public float temperature;
 | 
					    public float temperature;
 | 
				
			||||||
    public TileType type;
 | 
					    public TileType type;
 | 
				
			||||||
 | 
					    public float currentHealth;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -10,7 +10,7 @@ public class TileGrid : Resource, IReadOnlyList<Tile>
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    [Export]
 | 
					    [Export]
 | 
				
			||||||
    private Resource _startTileTypeResource;
 | 
					    private Resource _startTileTypeResource;
 | 
				
			||||||
    public TileType StartTileType => (TileType)_startTileTypeResource;
 | 
					    private TileType StartTileType => (TileType)_startTileTypeResource;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public int Count => Size * Size;
 | 
					    public int Count => Size * Size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -58,6 +58,7 @@ public class TileGrid : Resource, IReadOnlyList<Tile>
 | 
				
			|||||||
            tile.isHighlighted = false;
 | 
					            tile.isHighlighted = false;
 | 
				
			||||||
            tile.temperature = 0.0f;
 | 
					            tile.temperature = 0.0f;
 | 
				
			||||||
            tile.type = StartTileType;
 | 
					            tile.type = StartTileType;
 | 
				
			||||||
 | 
					            tile.currentHealth = 1.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            tiles.Add(tile);
 | 
					            tiles.Add(tile);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										7
									
								
								half-earth/scripts/tile/Wild.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								half-earth/scripts/tile/Wild.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					using Godot;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class Wild : TileType, IDamageable
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    [Export]
 | 
				
			||||||
 | 
					    public float Threshold { get; private set; }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user