heat #16
@ -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