riversong code showcase
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
using System.Collections.Generic;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
using Random = Unity.Mathematics.Random;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
public class MapDataInitializationOperation : IWorldGeneratorOperation
|
||||
{
|
||||
private const int HeightStep = 16;
|
||||
|
||||
[InjectService]
|
||||
private GameConfig _config;
|
||||
|
||||
public async UniTask Execute(World world)
|
||||
{
|
||||
var mapTexture = await GetRandomMapTextureAsync(world.Seed);
|
||||
|
||||
var worldSize = new int2(mapTexture.width, mapTexture.height);
|
||||
|
||||
world.Size = worldSize;
|
||||
world.Heightmap = new WorldHeightmap(worldSize);
|
||||
world.BlockMap = new BlockMap(worldSize);
|
||||
world.Fertility = new FertilityMap(worldSize);
|
||||
world.WaterMap = new WaterMap(worldSize);
|
||||
world.EntityIdMap = new EntityIdMap(worldSize);
|
||||
world.RoadNetwork = new RoadNetwork(worldSize);
|
||||
|
||||
ApplyMapTexture(world, mapTexture);
|
||||
|
||||
await InitializeWaterMapAsync(world);
|
||||
}
|
||||
|
||||
private async UniTask<Texture2D> GetRandomMapTextureAsync(int seed)
|
||||
{
|
||||
var config = _config.WorldGen;
|
||||
|
||||
var mapIndex = new Random((uint)seed).NextInt(config.MapTextures.Count);
|
||||
var mapTexture = await config.MapTextures[mapIndex].LoadAssetAsync<Texture2D>();
|
||||
|
||||
return mapTexture;
|
||||
}
|
||||
|
||||
private void ApplyMapTexture(World world, Texture2D mapTexture)
|
||||
{
|
||||
var mapData = mapTexture.GetPixelData<Color32>(0);
|
||||
var blockMapData = world.BlockMap.GetNativeArray();
|
||||
var fertilityData = world.Fertility.GetNativeArray();
|
||||
|
||||
for (var tileIndex = 0; tileIndex < mapData.Length; tileIndex++)
|
||||
{
|
||||
var color = mapData[tileIndex];
|
||||
|
||||
var h = color.r / HeightStep;
|
||||
world.Heightmap.SetValue(tileIndex, h);
|
||||
if (h != _config.GeneralSettings.BaseElevation)
|
||||
{
|
||||
blockMapData[tileIndex] |= BlockReason.InvalidElevation;
|
||||
continue;
|
||||
}
|
||||
|
||||
var fertility = (float)color.g / byte.MaxValue;
|
||||
fertilityData[tileIndex] = new FertilityMapValue
|
||||
{
|
||||
CurrentFertility = fertility,
|
||||
MaxFertility = fertility,
|
||||
LockId = Entity.InvalidId
|
||||
};
|
||||
|
||||
if (color.b > 0)
|
||||
{
|
||||
var stride = world.Size.x;
|
||||
var tile = new int2(tileIndex % stride, tileIndex / stride);
|
||||
world.CritterHerdsState.EligibleCenters.Add(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask InitializeWaterMapAsync(World world)
|
||||
{
|
||||
const int MaxWaterDistance = 3;
|
||||
|
||||
var budget = new AsyncBudget(world.Size.x * 8);
|
||||
var open = new Queue<int2>();
|
||||
|
||||
foreach (var tile in TileRange.From(0, world.Size - 1))
|
||||
{
|
||||
if (BelowWater(world, tile))
|
||||
open.Enqueue(tile);
|
||||
else
|
||||
world.WaterMap.SetValue(tile, int.MaxValue);
|
||||
|
||||
await budget.TickAsync();
|
||||
}
|
||||
|
||||
while (open.Count > 0)
|
||||
{
|
||||
var current = open.Dequeue();
|
||||
var currentDistance = world.WaterMap.GetValue(current);
|
||||
|
||||
if (currentDistance >= MaxWaterDistance) continue;
|
||||
|
||||
foreach (var direction in DirectionVectors.Directions8)
|
||||
{
|
||||
var other = current + direction;
|
||||
if (!world.Contains(other)) continue;
|
||||
|
||||
var distance = BelowWater(world, other) ? 0 : currentDistance + 1;
|
||||
if (distance >= world.WaterMap.GetValue(other)) continue;
|
||||
|
||||
world.WaterMap.SetValue(other, distance);
|
||||
if (distance < MaxWaterDistance) open.Enqueue(other);
|
||||
}
|
||||
|
||||
await budget.TickAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private bool BelowWater(World world, int2 tile)
|
||||
{
|
||||
return world.Heightmap.GetValue(tile) < _config.GeneralSettings.BaseElevation;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user