Also populate chunks with entities when chunks are being generated.
parent
928ddd3937
commit
4c0a2e7714
142
HexGrid.cs
142
HexGrid.cs
|
@ -6,31 +6,33 @@ using AxialCoordDirectionPair = System.Tuple<Godot.Vector2, Godot.Vector3>;
|
|||
|
||||
public class HexGrid : Resource
|
||||
{
|
||||
private Vector2 _baseHexSize = new(1, Mathf.Sqrt(3) / 2);
|
||||
private Vector2 _hexSize = new(1, Mathf.Sqrt(3) / 2);
|
||||
private readonly Vector2 _baseHexSize = new(1, Mathf.Sqrt(3) / 2);
|
||||
private Rect2 _boundsAxialCoords;
|
||||
private Vector2 _hexScale = new(1, 1);
|
||||
private Vector2 _hexSize = new(1, Mathf.Sqrt(3) / 2);
|
||||
private Transform2D _hexTransform;
|
||||
private Transform2D _hexTransformInv;
|
||||
private HexCell _minCoords = new();
|
||||
private HexCell _maxCoords = new();
|
||||
private Rect2 _boundsAxialCoords;
|
||||
private HexCell _minCoords = new();
|
||||
|
||||
public Dictionary<(Vector2, Vector3), float> Barriers = new();
|
||||
public int FindPathCheckedCellCount;
|
||||
|
||||
public Dictionary<Vector2, float> Obstacles = new();
|
||||
|
||||
public Dictionary<(Vector2, Vector3), float> Barriers = new();
|
||||
|
||||
|
||||
public float PathCostDefault = 1;
|
||||
public int FindPathCheckedCellCount;
|
||||
|
||||
public Vector2 HexSize
|
||||
public HexGrid()
|
||||
{
|
||||
get { return _hexSize; }
|
||||
HexScale = new Vector2(1, 1);
|
||||
}
|
||||
|
||||
public Vector2 HexSize => _hexSize;
|
||||
|
||||
public Vector2 HexScale
|
||||
{
|
||||
get { return _hexScale; }
|
||||
get => _hexScale;
|
||||
set
|
||||
{
|
||||
_hexScale = value;
|
||||
|
@ -45,11 +47,6 @@ public class HexGrid : Resource
|
|||
}
|
||||
}
|
||||
|
||||
public HexGrid()
|
||||
{
|
||||
HexScale = new Vector2(1, 1);
|
||||
}
|
||||
|
||||
public Vector2 GetHexCenter(HexCell cell)
|
||||
{
|
||||
return _hexTransform * cell.AxialCoords;
|
||||
|
@ -57,21 +54,29 @@ public class HexGrid : Resource
|
|||
|
||||
public Vector2 GetHexCenterFromOffset(Vector2 offsetCoord)
|
||||
{
|
||||
HexCell cell = new HexCell();
|
||||
var cell = new HexCell();
|
||||
cell.OffsetCoords = offsetCoord;
|
||||
return GetHexCenter(cell);
|
||||
}
|
||||
|
||||
public Vector3 GetHexCenterVec3FromOffset(Vector2 offsetCoord)
|
||||
{
|
||||
var cell = new HexCell();
|
||||
cell.OffsetCoords = offsetCoord;
|
||||
var hexCenter = GetHexCenter(cell);
|
||||
return new Vector3(hexCenter.x, 0, hexCenter.y);
|
||||
}
|
||||
|
||||
public HexCell GetHexAtOffset(Vector2 offsetCoord)
|
||||
{
|
||||
HexCell cell = new HexCell();
|
||||
var cell = new HexCell();
|
||||
cell.OffsetCoords = offsetCoord;
|
||||
return cell;
|
||||
}
|
||||
|
||||
public HexCell GetHexAt(Vector2 planeCoord)
|
||||
{
|
||||
HexCell result = new HexCell(_hexTransformInv * planeCoord);
|
||||
var result = new HexCell(_hexTransformInv * planeCoord);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -85,12 +90,12 @@ public class HexGrid : Resource
|
|||
_minCoords = minCell;
|
||||
_maxCoords = maxCell;
|
||||
_boundsAxialCoords = new Rect2(_minCoords.AxialCoords,
|
||||
(_maxCoords.AxialCoords - _minCoords.AxialCoords) + Vector2.One);
|
||||
_maxCoords.AxialCoords - _minCoords.AxialCoords + Vector2.One);
|
||||
}
|
||||
|
||||
public void SetBounds(HexCell center, int size)
|
||||
{
|
||||
Vector2 centerOffset = center.OffsetCoords;
|
||||
var centerOffset = center.OffsetCoords;
|
||||
SetBounds(GetHexAtOffset(centerOffset - Vector2.One * size / 2),
|
||||
GetHexAtOffset(centerOffset + Vector2.One * size / 2));
|
||||
}
|
||||
|
@ -123,10 +128,7 @@ public class HexGrid : Resource
|
|||
|
||||
public void RemoveBarrier(HexCell cell, Vector3 directionCube)
|
||||
{
|
||||
if (Barriers.ContainsKey((cell.AxialCoords, directionCube)))
|
||||
{
|
||||
Barriers.Remove((cell.AxialCoords, directionCube));
|
||||
}
|
||||
if (Barriers.ContainsKey((cell.AxialCoords, directionCube))) Barriers.Remove((cell.AxialCoords, directionCube));
|
||||
}
|
||||
|
||||
public float GetHexCost(HexCell cell)
|
||||
|
@ -136,10 +138,7 @@ public class HexGrid : Resource
|
|||
|
||||
public float GetHexCost(Vector2 axialCoords)
|
||||
{
|
||||
if (!_boundsAxialCoords.HasPoint(axialCoords))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (!_boundsAxialCoords.HasPoint(axialCoords)) return 0;
|
||||
|
||||
float value;
|
||||
return Obstacles.TryGetValue(axialCoords, out value) ? value : PathCostDefault;
|
||||
|
@ -147,29 +146,20 @@ public class HexGrid : Resource
|
|||
|
||||
public float GetMoveCost(Vector2 axialCoords, Vector3 directionCube)
|
||||
{
|
||||
HexCell startCell = new HexCell(axialCoords);
|
||||
HexCell targetCell = new HexCell(startCell.CubeCoords + directionCube);
|
||||
var startCell = new HexCell(axialCoords);
|
||||
var targetCell = new HexCell(startCell.CubeCoords + directionCube);
|
||||
|
||||
float cost = GetHexCost(axialCoords);
|
||||
if (cost == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
var cost = GetHexCost(axialCoords);
|
||||
if (cost == 0) return 0;
|
||||
|
||||
cost = GetHexCost(targetCell.AxialCoords);
|
||||
if (cost == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (cost == 0) return 0;
|
||||
|
||||
float barrierCost;
|
||||
if (Barriers.ContainsKey((axialCoords, directionCube)))
|
||||
{
|
||||
barrierCost = Barriers[(axialCoords, directionCube)];
|
||||
if (barrierCost == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (barrierCost == 0) return 0;
|
||||
|
||||
cost += barrierCost;
|
||||
}
|
||||
|
@ -177,10 +167,7 @@ public class HexGrid : Resource
|
|||
if (Barriers.ContainsKey((targetCell.AxialCoords, -directionCube)))
|
||||
{
|
||||
barrierCost = Barriers[(targetCell.AxialCoords, -directionCube)];
|
||||
if (barrierCost == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (barrierCost == 0) return 0;
|
||||
|
||||
cost += barrierCost;
|
||||
}
|
||||
|
@ -193,16 +180,14 @@ public class HexGrid : Resource
|
|||
{
|
||||
if (GetHexCost(toCell) == 0)
|
||||
{
|
||||
HexCell[] line = fromCell.LineTo(toCell);
|
||||
var line = fromCell.LineTo(toCell);
|
||||
|
||||
foreach (int i in Enumerable.Range(1, line.Length))
|
||||
{
|
||||
foreach (var i in Enumerable.Range(1, line.Length))
|
||||
if (GetHexCost(line[i]) == 0)
|
||||
{
|
||||
toCell = line[i - 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return toCell;
|
||||
|
@ -210,13 +195,13 @@ public class HexGrid : Resource
|
|||
|
||||
public List<HexCell> FindPath(HexCell startHex, HexCell goalHex)
|
||||
{
|
||||
Vector2 goalAxialCoords = goalHex.AxialCoords;
|
||||
var goalAxialCoords = goalHex.AxialCoords;
|
||||
|
||||
SimplePriorityQueue<Vector2, float> frontier = new SimplePriorityQueue<Vector2, float>();
|
||||
var frontier = new SimplePriorityQueue<Vector2, float>();
|
||||
frontier.Enqueue(startHex.AxialCoords, 0);
|
||||
Dictionary<Vector2, Vector2> cameFrom =
|
||||
var cameFrom =
|
||||
new Dictionary<Vector2, Vector2>();
|
||||
Dictionary<Vector2, float> costSoFar =
|
||||
var costSoFar =
|
||||
new Dictionary<Vector2, float>();
|
||||
|
||||
cameFrom.Add(startHex.AxialCoords, startHex.AxialCoords);
|
||||
|
@ -227,20 +212,17 @@ public class HexGrid : Resource
|
|||
while (frontier.Any())
|
||||
{
|
||||
FindPathCheckedCellCount++;
|
||||
HexCell currentHex = new HexCell(frontier.Dequeue());
|
||||
Vector2 currentAxial = currentHex.AxialCoords;
|
||||
var currentHex = new HexCell(frontier.Dequeue());
|
||||
var currentAxial = currentHex.AxialCoords;
|
||||
|
||||
if (currentHex == goalHex)
|
||||
if (currentHex == goalHex) break;
|
||||
|
||||
foreach (var nextHex in currentHex.GetAllAdjacent())
|
||||
{
|
||||
break;
|
||||
}
|
||||
var nextAxial = nextHex.AxialCoords;
|
||||
var nextCost = GetMoveCost(currentAxial, new HexCell(nextAxial - currentHex.AxialCoords).CubeCoords);
|
||||
|
||||
foreach (HexCell nextHex in currentHex.GetAllAdjacent())
|
||||
{
|
||||
Vector2 nextAxial = nextHex.AxialCoords;
|
||||
float nextCost = GetMoveCost(currentAxial, new HexCell(nextAxial - currentHex.AxialCoords).CubeCoords);
|
||||
|
||||
if ((nextHex == goalHex) && (GetHexCost(nextAxial) == 0))
|
||||
if (nextHex == goalHex && GetHexCost(nextAxial) == 0)
|
||||
{
|
||||
// Goal ist an obstacle
|
||||
cameFrom[nextHex.AxialCoords] = currentHex.AxialCoords;
|
||||
|
@ -248,16 +230,13 @@ public class HexGrid : Resource
|
|||
break;
|
||||
}
|
||||
|
||||
if (nextCost == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (nextCost == 0) continue;
|
||||
|
||||
nextCost += costSoFar[currentHex.AxialCoords];
|
||||
if (!costSoFar.ContainsKey(nextHex.AxialCoords) || nextCost < costSoFar[nextHex.AxialCoords])
|
||||
{
|
||||
costSoFar[nextHex.AxialCoords] = nextCost;
|
||||
float priority = nextCost + nextHex.DistanceTo(goalHex);
|
||||
var priority = nextCost + nextHex.DistanceTo(goalHex);
|
||||
|
||||
frontier.Enqueue(nextHex.AxialCoords, priority);
|
||||
cameFrom[nextHex.AxialCoords] = currentHex.AxialCoords;
|
||||
|
@ -267,19 +246,16 @@ public class HexGrid : Resource
|
|||
|
||||
// GD.Print("Checked Cell Count: " + FindPathCheckedCellCount);
|
||||
|
||||
List<HexCell> result = new List<HexCell>();
|
||||
var result = new List<HexCell>();
|
||||
if (!cameFrom.ContainsKey(goalHex.AxialCoords))
|
||||
{
|
||||
GD.Print("Failed to find path from " + startHex + " to " + goalHex);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (GetHexCost(goalAxialCoords) != 0)
|
||||
{
|
||||
result.Add(goalHex);
|
||||
}
|
||||
if (GetHexCost(goalAxialCoords) != 0) result.Add(goalHex);
|
||||
|
||||
HexCell pathHex = goalHex;
|
||||
var pathHex = goalHex;
|
||||
while (pathHex != startHex)
|
||||
{
|
||||
pathHex = new HexCell(cameFrom[pathHex.AxialCoords]);
|
||||
|
@ -292,20 +268,20 @@ public class HexGrid : Resource
|
|||
|
||||
public List<HexCell> GetCellsForLine(Vector2 fromPlane, Vector2 toPlane)
|
||||
{
|
||||
List<HexCell> result = new List<HexCell>();
|
||||
var result = new List<HexCell>();
|
||||
|
||||
float distance = (toPlane - fromPlane).Length();
|
||||
Vector2 direction = (toPlane - fromPlane) / distance;
|
||||
var distance = (toPlane - fromPlane).Length();
|
||||
var direction = (toPlane - fromPlane) / distance;
|
||||
|
||||
Vector2 currentPointPlane = fromPlane;
|
||||
HexCell currentCell = GetHexAt(currentPointPlane);
|
||||
var currentPointPlane = fromPlane;
|
||||
var currentCell = GetHexAt(currentPointPlane);
|
||||
float currentDistance = 0;
|
||||
|
||||
do
|
||||
{
|
||||
result.Add(currentCell);
|
||||
GetHexCenter(currentCell);
|
||||
Vector2 currentPointLocal = currentPointPlane - GetHexCenter(currentCell);
|
||||
var currentPointLocal = currentPointPlane - GetHexCenter(currentCell);
|
||||
|
||||
int neighbourIndex;
|
||||
float boundaryPlaneDistance;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
name="PirateGame3D"
|
||||
platform="Android"
|
||||
runnable=true
|
||||
runnable=false
|
||||
custom_features=""
|
||||
export_filter="all_resources"
|
||||
include_filter=""
|
||||
|
@ -15,7 +15,7 @@ script_encryption_key=""
|
|||
|
||||
custom_template/debug=""
|
||||
custom_template/release=""
|
||||
custom_build/use_custom_build=true
|
||||
custom_build/use_custom_build=false
|
||||
custom_build/export_format=0
|
||||
custom_build/min_sdk=""
|
||||
custom_build/target_sdk=""
|
||||
|
|
|
@ -132,5 +132,7 @@ common/enable_pause_aware_picking=true
|
|||
|
||||
[rendering]
|
||||
|
||||
quality/shadows/filter_mode.mobile=1
|
||||
quality/directional_shadow/size.mobile=512
|
||||
quality/shadow_atlas/size.mobile=1024
|
||||
quality/subsurface_scattering/quality=0
|
||||
environment/default_environment="res://default_env.tres"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[gd_scene load_steps=19 format=2]
|
||||
[gd_scene load_steps=24 format=2]
|
||||
|
||||
[ext_resource path="res://scenes/StreamContainer.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://entities/Player.tscn" type="PackedScene" id=2]
|
||||
|
@ -15,6 +15,11 @@
|
|||
[ext_resource path="res://assets/Environment/HexTileMesh.tres" type="CylinderMesh" id=13]
|
||||
[ext_resource path="res://entities/Axe.tscn" type="PackedScene" id=14]
|
||||
[ext_resource path="res://systems/InteractionSystem.cs" type="Script" id=15]
|
||||
[ext_resource path="res://entities/rockA.tscn" type="PackedScene" id=16]
|
||||
[ext_resource path="res://entities/rockC.tscn" type="PackedScene" id=17]
|
||||
[ext_resource path="res://entities/rockB.tscn" type="PackedScene" id=18]
|
||||
[ext_resource path="res://entities/Tree.tscn" type="PackedScene" id=19]
|
||||
[ext_resource path="res://assets/Environment/grassLarge.tscn" type="PackedScene" id=20]
|
||||
|
||||
[sub_resource type="Animation" id=25]
|
||||
resource_name = "FlashLabel"
|
||||
|
@ -35,7 +40,9 @@ tracks/0/keys = {
|
|||
[sub_resource type="AnimationNodeStateMachinePlayback" id=26]
|
||||
|
||||
[sub_resource type="MultiMesh" id=27]
|
||||
color_format = 1
|
||||
transform_format = 1
|
||||
custom_data_format = 1
|
||||
visible_instance_count = 0
|
||||
mesh = ExtResource( 13 )
|
||||
|
||||
|
@ -351,9 +358,6 @@ script = ExtResource( 15 )
|
|||
[node name="Player" parent="." instance=ExtResource( 2 )]
|
||||
TileWorldNode = NodePath("../TileWorld")
|
||||
|
||||
[node name="Skeleton" parent="Player/Geometry/Armature" index="0"]
|
||||
bones/4/bound_children = [ ]
|
||||
|
||||
[node name="ToolAttachement" parent="Player/Geometry/Armature/Skeleton" index="5"]
|
||||
transform = Transform( 1, 8.68458e-08, -1.04308e-07, 1.74623e-07, -1, -1.30385e-07, 1.41561e-07, 1.50874e-07, -1, -0.72, 0.45, 3.28113e-08 )
|
||||
|
||||
|
@ -382,6 +386,26 @@ World = NodePath("..")
|
|||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -2.5, 0 )
|
||||
multimesh = SubResource( 27 )
|
||||
|
||||
[node name="Assets" type="Spatial" parent="World"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -5, 0 )
|
||||
visible = false
|
||||
|
||||
[node name="Rocks" type="Spatial" parent="World/Assets"]
|
||||
|
||||
[node name="rockA" parent="World/Assets/Rocks" instance=ExtResource( 16 )]
|
||||
|
||||
[node name="rockB" parent="World/Assets/Rocks" instance=ExtResource( 18 )]
|
||||
|
||||
[node name="rockC" parent="World/Assets/Rocks" instance=ExtResource( 17 )]
|
||||
|
||||
[node name="Grass" type="Spatial" parent="World/Assets"]
|
||||
|
||||
[node name="grassLarge" parent="World/Assets/Grass" instance=ExtResource( 20 )]
|
||||
|
||||
[node name="Trees" type="Spatial" parent="World/Assets"]
|
||||
|
||||
[node name="tree" parent="World/Assets/Trees" instance=ExtResource( 19 )]
|
||||
|
||||
[connection signal="toggled" from="DebugContainer/DebugStatsContainer/DebugMenuButton" to="DebugContainer/DebugStatsContainer" method="_on_DebugMenuButton_toggled"]
|
||||
[connection signal="value_changed" from="Generator Container/WorldGeneratorContainer/HBoxContainer/WorldSizeSlider" to="Generator Container/WorldGeneratorContainer" method="_on_HSlider_value_changed"]
|
||||
[connection signal="toggled" from="Generator Container/WorldGeneratorContainer/ShowTexturesCheckButton" to="Generator Container/WorldGeneratorContainer" method="_on_ShowTexturesCheckButton_toggled"]
|
||||
|
|
|
@ -142,6 +142,7 @@ public class TileInstanceManager : Spatial
|
|||
foreach (var j in Enumerable.Range(0, chunkSize))
|
||||
{
|
||||
var tile3D = (HexTile3D)_hexTile3DScene.Instance();
|
||||
tile3D.Cell.OffsetCoords = new Vector2(chunkIndex * global::World.ChunkSize + new Vector2(i, j));
|
||||
|
||||
var tileTransform = Transform.Identity;
|
||||
var centerPlaneCoord = HexGrid.GetHexCenterFromOffset(new Vector2(i, j));
|
||||
|
@ -181,7 +182,7 @@ public class TileInstanceManager : Spatial
|
|||
|
||||
var tileOrientation = new Basis(Vector3.Up, 90f * Mathf.Pi / 180f);
|
||||
|
||||
GD.Print("Updating transforms for instances of chunk " + value);
|
||||
GD.Print("Updating transforms for instances of chunk " + value + " origin: " + chunkTransform.origin);
|
||||
|
||||
foreach (var i in Enumerable.Range(0, TileInstanceIndices.Count))
|
||||
{
|
||||
|
@ -190,6 +191,7 @@ public class TileInstanceManager : Spatial
|
|||
|
||||
var tilePlaneCoord =
|
||||
HexGrid.GetHexCenterFromOffset(new Vector2(column, row));
|
||||
|
||||
_multiMeshInstance.Multimesh.SetInstanceTransform(TileInstanceIndices[i],
|
||||
new Transform(tileOrientation,
|
||||
chunkTransform.origin + new Vector3(tilePlaneCoord.x, 0, tilePlaneCoord.y)));
|
||||
|
|
|
@ -17,16 +17,18 @@ public class World : Spatial
|
|||
}
|
||||
|
||||
// constants
|
||||
public const int ChunkSize = 16;
|
||||
public const int ChunkSize = 10;
|
||||
public const int NumChunkRows = 3;
|
||||
public const int NumChunkColumns = NumChunkRows;
|
||||
private static readonly Color RockColor = new(0.5f, 0.5f, 0.4f);
|
||||
private static readonly Color GrassColor = new(0, 0.4f, 0);
|
||||
private static readonly Color DarkGrassColor = new(0.05882353f, 0.5411765f, 0.05882353f);
|
||||
private static readonly Color LightWaterColor = new(0.05882353f, 0.05882353f, 0.8627451f);
|
||||
|
||||
private readonly List<Vector2> _addedChunkIndices = new();
|
||||
private readonly Godot.Collections.Dictionary<Vector2, WorldChunk> _cachedWorldChunks;
|
||||
|
||||
private readonly Image _heightmapImage = new();
|
||||
|
||||
private readonly List<Vector2> _removedChunkIndices = new();
|
||||
|
||||
private readonly Image _tileTypeMapImage = new();
|
||||
|
||||
// referenced scenes
|
||||
|
@ -39,10 +41,13 @@ public class World : Spatial
|
|||
|
||||
// other members
|
||||
private Vector2 _centerPlaneCoord;
|
||||
private Array<Spatial> _grassAssets;
|
||||
private ImageTexture _heightmapTexture;
|
||||
|
||||
private OpenSimplexNoise _noiseGenerator = new();
|
||||
private Array<Spatial> _rockAssets;
|
||||
private TileInstanceManager _tileInstanceManager;
|
||||
private Array<Spatial> _treeAssets;
|
||||
private ImageTexture _viewTileTypeTexture;
|
||||
public Vector2 CenterChunkIndex = Vector2.Zero;
|
||||
public Spatial Chunks;
|
||||
|
@ -71,6 +76,17 @@ public class World : Spatial
|
|||
|
||||
InitNoiseGenerator();
|
||||
|
||||
GetNode<Spatial>("Assets").Visible = false;
|
||||
|
||||
_rockAssets = new Array<Spatial>();
|
||||
foreach (Spatial asset in GetNode<Node>("Assets/Rocks").GetChildren()) _rockAssets.Add(asset);
|
||||
|
||||
_grassAssets = new Array<Spatial>();
|
||||
foreach (Spatial asset in GetNode<Node>("Assets/Grass").GetChildren()) _grassAssets.Add(asset);
|
||||
|
||||
_treeAssets = new Array<Spatial>();
|
||||
foreach (Spatial asset in GetNode<Node>("Assets/Trees").GetChildren()) _treeAssets.Add(asset);
|
||||
|
||||
SetCenterPlaneCoord(Vector2.Zero);
|
||||
}
|
||||
|
||||
|
@ -129,6 +145,78 @@ public class World : Spatial
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
private bool IsColorEqualApprox(Color colorA, Color colorB)
|
||||
{
|
||||
var colorDifference = new Vector3(colorA.r - colorB.r, colorA.g - colorB.g, colorA.b - colorB.b);
|
||||
return colorDifference.LengthSquared() < 0.1 * 0.1;
|
||||
}
|
||||
|
||||
private Spatial SelectAsset(Vector2 offsetCoord, Array<Spatial> assets, Random randomGenerator, double probability)
|
||||
{
|
||||
if (randomGenerator.NextDouble() < 1.0 - probability) return null;
|
||||
|
||||
var assetIndex = randomGenerator.Next(assets.Count);
|
||||
var assetInstance = (Spatial)assets[assetIndex].Duplicate();
|
||||
var assetTransform = Transform.Identity;
|
||||
assetTransform.origin = HexGrid.GetHexCenterVec3FromOffset(offsetCoord);
|
||||
// TODO: assetTransform.origin.y = GetHeightAtOffset(offsetCoord);
|
||||
assetTransform.origin.y = 0;
|
||||
assetTransform.basis =
|
||||
assetTransform.basis.Rotated(Vector3.Up, (float)(randomGenerator.NextDouble() * Mathf.Pi * 2));
|
||||
assetInstance.Transform = assetTransform;
|
||||
|
||||
return assetInstance;
|
||||
}
|
||||
|
||||
private void PopulateChunk(WorldChunk chunk)
|
||||
{
|
||||
var environmentRandom = new Random(Seed);
|
||||
|
||||
var tileTypeImage = chunk.TileTypeOffscreenViewport.GetTexture().GetData();
|
||||
tileTypeImage.Lock();
|
||||
|
||||
foreach (var textureCoordU in Enumerable.Range(0, chunk.Size))
|
||||
foreach (var textureCoordV in Enumerable.Range(0, chunk.Size))
|
||||
{
|
||||
var colorValue = tileTypeImage.GetPixel(textureCoordU, textureCoordV);
|
||||
var textureCoord = new Vector2(textureCoordU, textureCoordV);
|
||||
var offsetCoord = chunk.ChunkIndex * ChunkSize + textureCoord;
|
||||
|
||||
if (IsColorEqualApprox(colorValue, RockColor))
|
||||
{
|
||||
var rockAsset = SelectAsset(offsetCoord, _rockAssets, environmentRandom, 0.15);
|
||||
if (rockAsset != null) chunk.Entities.AddChild(rockAsset);
|
||||
// TODO: MarkCellUnwalkable(cell);
|
||||
}
|
||||
else if (IsColorEqualApprox(colorValue, GrassColor) || IsColorEqualApprox(colorValue, DarkGrassColor))
|
||||
{
|
||||
var grassAsset = SelectAsset(offsetCoord, _grassAssets, environmentRandom, 0.15);
|
||||
if (grassAsset != null) chunk.Entities.AddChild(grassAsset);
|
||||
|
||||
var treeAsset = SelectAsset(offsetCoord, _treeAssets, environmentRandom, 0.05);
|
||||
if (treeAsset != null) chunk.Entities.AddChild(treeAsset);
|
||||
// TODO: MarkCellUnwalkable(cell);
|
||||
// else if (environmentRandom.NextDouble() < 0.01)
|
||||
// {
|
||||
// var chestAsset = (Chest)_chestScene.Instance();
|
||||
// var assetTransform = Transform.Identity;
|
||||
// assetTransform.origin = GetHexCenterFromOffset(offsetCoord);
|
||||
// assetTransform.origin.y = GetHeightAtOffset(offsetCoord);
|
||||
// chestAsset.Transform = assetTransform;
|
||||
// Entities.AddChild(chestAsset);
|
||||
// MarkCellUnwalkable(cell);
|
||||
// }
|
||||
}
|
||||
// else if (IsColorWater(colorValue))
|
||||
// {
|
||||
// MarkCellUnwalkable(cell);
|
||||
// }
|
||||
}
|
||||
|
||||
tileTypeImage.Unlock();
|
||||
}
|
||||
|
||||
public void UpdateCenterChunkFromPlaneCoord(Vector2 planeCoord)
|
||||
{
|
||||
if (State != GenerationState.Done)
|
||||
|
@ -338,6 +426,8 @@ public class World : Spatial
|
|||
else if (State == GenerationState.Objects)
|
||||
{
|
||||
// generate objects
|
||||
foreach (var chunkIndex in _addedChunkIndices) PopulateChunk(_cachedWorldChunks[chunkIndex]);
|
||||
|
||||
State = GenerationState.Done;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,16 +4,16 @@ using Godot;
|
|||
|
||||
public class WorldChunk : Spatial
|
||||
{
|
||||
private readonly SpatialMaterial _rectMaterial = new();
|
||||
private Sprite _heightmapSprite;
|
||||
private TextureRect _heightmapTextureRect;
|
||||
private Sprite _noiseMask;
|
||||
|
||||
private Sprite _noiseSprite;
|
||||
|
||||
private readonly SpatialMaterial _rectMaterial = new();
|
||||
private bool _showTextureOverlay;
|
||||
[Export] public Vector2 ChunkIndex;
|
||||
public Color DebugColor = Colors.White;
|
||||
[Export] public Spatial Entities;
|
||||
[Export] public Texture HeightMap;
|
||||
public int HeightMapFrameCount;
|
||||
|
||||
|
@ -91,6 +91,9 @@ public class WorldChunk : Spatial
|
|||
TileTypeOffscreenViewport.Size = Vector2.One * Size;
|
||||
Debug.Assert(TileTypeOffscreenViewport != null);
|
||||
|
||||
Entities = (Spatial)FindNode("Entities");
|
||||
Debug.Assert(Entities != null);
|
||||
|
||||
SetSize(World.ChunkSize);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue