Added very basic chunk unloading.
parent
f8819937e1
commit
30b70d1d7a
|
@ -2,6 +2,7 @@ using Godot;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
public class World : Spatial
|
public class World : Spatial
|
||||||
{
|
{
|
||||||
|
@ -9,7 +10,7 @@ public class World : Spatial
|
||||||
private PackedScene _worldChunkScene = GD.Load<PackedScene>("res://scenes/WorldChunk.tscn");
|
private PackedScene _worldChunkScene = GD.Load<PackedScene>("res://scenes/WorldChunk.tscn");
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
public const int ChunkSize = 4;
|
public const int ChunkSize = 16;
|
||||||
public HexGrid HexGrid = new HexGrid();
|
public HexGrid HexGrid = new HexGrid();
|
||||||
public Spatial Chunks;
|
public Spatial Chunks;
|
||||||
public Color DebugColor;
|
public Color DebugColor;
|
||||||
|
@ -32,13 +33,16 @@ public class World : Spatial
|
||||||
private int[] _previousCenterChunkCoord = { 0, 0 };
|
private int[] _previousCenterChunkCoord = { 0, 0 };
|
||||||
private Rect2 _centerChunkRect2 = new Rect2();
|
private Rect2 _centerChunkRect2 = new Rect2();
|
||||||
private Random _debugColorRandom = new Random();
|
private Random _debugColorRandom = new Random();
|
||||||
private Dictionary<Tuple<int, int>, WorldChunk> _worldChunks;
|
private Dictionary<Tuple<int, int>, WorldChunk> _cachedWorldChunks;
|
||||||
|
private List<Tuple<int, int>> _activeChunkIndices = new();
|
||||||
|
private List<Tuple<int, int>> _addedChunkIndices = new();
|
||||||
|
private List<Tuple<int, int>> _removedChunkIndices = new();
|
||||||
|
|
||||||
public World()
|
public World()
|
||||||
{
|
{
|
||||||
Debug.Assert(ChunkSize % 2 == 0);
|
Debug.Assert(ChunkSize % 2 == 0);
|
||||||
|
|
||||||
_worldChunks = new Dictionary<Tuple<int, int>, WorldChunk>();
|
_cachedWorldChunks = new Dictionary<Tuple<int, int>, WorldChunk>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the node enters the scene tree for the first time.
|
// Called when the node enters the scene tree for the first time.
|
||||||
|
@ -52,15 +56,20 @@ public class World : Spatial
|
||||||
|
|
||||||
public WorldChunk GetOrCreateWorldChunk(int xIndex, int yIndex, Color debugColor)
|
public WorldChunk GetOrCreateWorldChunk(int xIndex, int yIndex, Color debugColor)
|
||||||
{
|
{
|
||||||
if (_worldChunks.ContainsKey(new Tuple<int, int>(xIndex, yIndex)))
|
if (IsTileCached(xIndex, yIndex))
|
||||||
{
|
{
|
||||||
WorldChunk cachedChunk = _worldChunks[new Tuple<int, int>(xIndex, yIndex)];
|
WorldChunk cachedChunk = _cachedWorldChunks[new Tuple<int, int>(xIndex, yIndex)];
|
||||||
return cachedChunk;
|
return cachedChunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreateWorldChunk(xIndex, yIndex, debugColor);
|
return CreateWorldChunk(xIndex, yIndex, debugColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsTileCached(int xIndex, int yIndex)
|
||||||
|
{
|
||||||
|
return _cachedWorldChunks.ContainsKey(new Tuple<int, int>(xIndex, yIndex));
|
||||||
|
}
|
||||||
|
|
||||||
private WorldChunk CreateWorldChunk(int xIndex, int yIndex, Color debugColor)
|
private WorldChunk CreateWorldChunk(int xIndex, int yIndex, Color debugColor)
|
||||||
{
|
{
|
||||||
WorldChunk result = (WorldChunk)_worldChunkScene.Instance();
|
WorldChunk result = (WorldChunk)_worldChunkScene.Instance();
|
||||||
|
@ -73,6 +82,7 @@ public class World : Spatial
|
||||||
Vector2 planeCoordNorthEast = HexGrid.GetHexCenterFromOffset(offsetCoordNorthEast) +
|
Vector2 planeCoordNorthEast = HexGrid.GetHexCenterFromOffset(offsetCoordNorthEast) +
|
||||||
new Vector2(HexGrid.HexSize.x, -HexGrid.HexSize.y) * 0.5f;
|
new Vector2(HexGrid.HexSize.x, -HexGrid.HexSize.y) * 0.5f;
|
||||||
|
|
||||||
|
result.ChunkAddress = new Vector2(xIndex, yIndex);
|
||||||
result.PlaneRect = new Rect2(
|
result.PlaneRect = new Rect2(
|
||||||
new Vector2(planeCoordSouthWest.x, planeCoordNorthEast.y),
|
new Vector2(planeCoordSouthWest.x, planeCoordNorthEast.y),
|
||||||
new Vector2(planeCoordNorthEast.x - planeCoordSouthWest.x, planeCoordSouthWest.y - planeCoordNorthEast.y));
|
new Vector2(planeCoordNorthEast.x - planeCoordSouthWest.x, planeCoordSouthWest.y - planeCoordNorthEast.y));
|
||||||
|
@ -82,21 +92,86 @@ public class World : Spatial
|
||||||
|
|
||||||
Chunks.AddChild(result);
|
Chunks.AddChild(result);
|
||||||
Tuple<int, int> chunkIndex = new Tuple<int, int>(xIndex, yIndex);
|
Tuple<int, int> chunkIndex = new Tuple<int, int>(xIndex, yIndex);
|
||||||
_worldChunks.Add(chunkIndex, result);
|
_cachedWorldChunks.Add(chunkIndex, result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateCenterChunkFromPlaneCoord(Vector2 planeCoord)
|
public void UpdateCenterChunkFromPlaneCoord(Vector2 planeCoord)
|
||||||
{
|
{
|
||||||
HexCell centerOffsetCoord = HexGrid.GetHexAt(planeCoord);
|
// mark all chunks as retired
|
||||||
Vector2 chunkIndexFloatUnrounded = (centerOffsetCoord.OffsetCoords / (float)ChunkSize);
|
Dictionary<Tuple<int, int>, WorldChunk> oldCachedChunks = new(_cachedWorldChunks);
|
||||||
Vector2 chunkIndexFloat = (centerOffsetCoord.OffsetCoords / (float)ChunkSize).Floor();
|
|
||||||
Tuple<int, int> chunkIndex = new Tuple<int, int>((int)chunkIndexFloat.x, (int)chunkIndexFloat.y);
|
// set new center chunk
|
||||||
|
var chunkIndex = GetChunkTupleFromPlaneCoord(planeCoord);
|
||||||
WorldChunk currentChunk = GetOrCreateWorldChunk(chunkIndex.Item1, chunkIndex.Item2,
|
WorldChunk currentChunk = GetOrCreateWorldChunk(chunkIndex.Item1, chunkIndex.Item2,
|
||||||
new Color(GD.Randf(), GD.Randf(), GD.Randf()));
|
new Color(GD.Randf(), GD.Randf(), GD.Randf()));
|
||||||
_centerChunkRect2 = currentChunk.PlaneRect;
|
_centerChunkRect2 = currentChunk.PlaneRect;
|
||||||
|
|
||||||
|
// load or create adjacent chunks
|
||||||
|
_activeChunkIndices = new List<Tuple<int, int>>();
|
||||||
|
_activeChunkIndices.Add(new Tuple<int, int>(chunkIndex.Item1 - 1, chunkIndex.Item2 - 1));
|
||||||
|
_activeChunkIndices.Add(new Tuple<int, int>(chunkIndex.Item1, chunkIndex.Item2 - 1));
|
||||||
|
_activeChunkIndices.Add(new Tuple<int, int>(chunkIndex.Item1 + 1, chunkIndex.Item2 - 1));
|
||||||
|
|
||||||
|
_activeChunkIndices.Add(new Tuple<int, int>(chunkIndex.Item1 - 1, chunkIndex.Item2));
|
||||||
|
_activeChunkIndices.Add(new Tuple<int, int>(chunkIndex.Item1, chunkIndex.Item2));
|
||||||
|
_activeChunkIndices.Add(new Tuple<int, int>(chunkIndex.Item1 + 1, chunkIndex.Item2));
|
||||||
|
|
||||||
|
_activeChunkIndices.Add(new Tuple<int, int>(chunkIndex.Item1 - 1, chunkIndex.Item2 + 1));
|
||||||
|
_activeChunkIndices.Add(new Tuple<int, int>(chunkIndex.Item1, chunkIndex.Item2 + 1));
|
||||||
|
_activeChunkIndices.Add(new Tuple<int, int>(chunkIndex.Item1 + 1, chunkIndex.Item2 + 1));
|
||||||
|
|
||||||
|
foreach(Tuple<int, int> activeChunkIndex in _activeChunkIndices)
|
||||||
|
{
|
||||||
|
GetOrCreateWorldChunk(activeChunkIndex.Item1, activeChunkIndex.Item2, new Color(GD.Randf(), GD.Randf(), GD.Randf()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// unload retired chunks
|
||||||
|
_removedChunkIndices.Clear();
|
||||||
|
_addedChunkIndices.Clear();
|
||||||
|
|
||||||
|
foreach (var cachedChunkKey in oldCachedChunks.Keys)
|
||||||
|
{
|
||||||
|
if (!_activeChunkIndices.Contains(cachedChunkKey))
|
||||||
|
{
|
||||||
|
RemoveChunk(cachedChunkKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var chunkKey in _activeChunkIndices)
|
||||||
|
{
|
||||||
|
if (!oldCachedChunks.ContainsKey(chunkKey))
|
||||||
|
{
|
||||||
|
_addedChunkIndices.Add(chunkKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GD.Print("Removed Chunks " + _removedChunkIndices.Count);
|
||||||
|
GD.Print("Added Chunks " + _addedChunkIndices.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveChunk(Tuple<int, int> cachedChunkKey)
|
||||||
|
{
|
||||||
|
_cachedWorldChunks.Remove(cachedChunkKey);
|
||||||
|
_removedChunkIndices.Add(cachedChunkKey);
|
||||||
|
|
||||||
|
foreach (WorldChunk chunk in Chunks.GetChildren())
|
||||||
|
{
|
||||||
|
if (chunk.ChunkAddress == new Vector2(cachedChunkKey.Item1, cachedChunkKey.Item2))
|
||||||
|
{
|
||||||
|
chunk.QueueFree();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Tuple<int, int> GetChunkTupleFromPlaneCoord(Vector2 planeCoord)
|
||||||
|
{
|
||||||
|
HexCell centerOffsetCoord = HexGrid.GetHexAt(planeCoord);
|
||||||
|
Vector2 chunkIndexFloat = (centerOffsetCoord.OffsetCoords / (float)ChunkSize).Floor();
|
||||||
|
Tuple<int, int> chunkIndex = new Tuple<int, int>((int)chunkIndexFloat.x, (int)chunkIndexFloat.y);
|
||||||
|
return chunkIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetCenterPlaneCoord(Vector2 centerPlaneCoord)
|
public void SetCenterPlaneCoord(Vector2 centerPlaneCoord)
|
||||||
|
|
Loading…
Reference in New Issue