Compare commits

...

2 Commits

Author SHA1 Message Date
veniti
476411f6e7 dodano strefy wpływów miast 2019-11-21 20:40:35 +01:00
veniti
4facf6c3ba dodano oznaczanie działek 2019-11-18 23:56:28 +01:00
8 changed files with 190 additions and 646 deletions

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,10 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using Assets.Cities; using Assets.Cities;
using Assets.Common; using Assets.Common;
using System;
using Assets.Voronoi; using Assets.Voronoi;
using UnityEngine;
using Random = System.Random;
namespace Assets.AnnotationPass namespace Assets.AnnotationPass
{ {
@ -18,6 +21,7 @@ namespace Assets.AnnotationPass
public double MinNudgeDistance { get; set; } = .75; public double MinNudgeDistance { get; set; } = .75;
public double MinimumRoadLength { get; set; } = 2; public double MinimumRoadLength { get; set; } = 2;
public double BusinessCityFields { get; set; } = 0.3;
public CityFieldsPass(Random random) public CityFieldsPass(Random random)
{ {
@ -120,6 +124,8 @@ namespace Assets.AnnotationPass
(current, next) = (next, GetNext(next, current)); (current, next) = (next, GetNext(next, current));
} while (current != start && watchdog-- > 0); } while (current != start && watchdog-- > 0);
field.Center = PointUtils.Mean(field.Boundary);
return field; return field;
} }
@ -133,6 +139,26 @@ namespace Assets.AnnotationPass
// remove outside field // remove outside field
city.Fields.RemoveAll(field => !PointUtils.IsClockwise(field.Boundary)); city.Fields.RemoveAll(field => !PointUtils.IsClockwise(field.Boundary));
// add field types
var orderedFields = city.Fields.OrderBy(cf => Point.Dist(cf.Center, city.Center)).ToList();
orderedFields.First().Type = FieldType.MainSquare;
int businessCityFields = (int)Math.Ceiling((BusinessCityFields*orderedFields.Count()));
foreach (var cityField in orderedFields.Skip(1).Take(businessCityFields))
{
cityField.Type = FieldType.Business;
}
foreach (var cityField in orderedFields.Skip(1+businessCityFields))
{
cityField.Type = FieldType.Living;
}
} }
public void Annotate(Map map) public void Annotate(Map map)

View File

@ -10,7 +10,12 @@ namespace Assets.AnnotationPass
{ {
public const string CitiesProperty = "Cities"; public const string CitiesProperty = "Cities";
public const string CityProperty = "City"; public const string CityProperty = "City";
public int MaxCitiesCount { get; set; } = 20;
public int MaxPlacementTries { get; set; } = 30;
public float RangeOfInfluence { get; set; } = .5f;
public float CitiesSize { get; set; } = .5f;
private Graph<Location> _locationGraph; private Graph<Location> _locationGraph;
private Graph<MapSite> _basicGraph; private Graph<MapSite> _basicGraph;
private Random _random; private Random _random;
@ -20,16 +25,14 @@ namespace Assets.AnnotationPass
_random = random ?? new Random(); _random = random ?? new Random();
} }
IEnumerable<int> LocateCities()
{
return ChoosePoints(5);
}
City CreateCity(int vertex, int size) City CreateCity(int vertex, int size)
{ {
City newCity = new City(); City newCity = new City();
var site = _basicGraph.Vertices[vertex]; var site = _basicGraph.Vertices[vertex];
newCity.Center = site.Center.Clone() as Point;
site.Tags.Add("City.Center");
var sites = new List<MapSite> { site }; var sites = new List<MapSite> { site };
var location = site.Metadata.GetProperty<Location>(LandmassPass.SiteLocationProperty); var location = site.Metadata.GetProperty<Location>(LandmassPass.SiteLocationProperty);
@ -46,35 +49,47 @@ namespace Assets.AnnotationPass
s.Metadata.SetProperty(CityProperty, newCity); s.Metadata.SetProperty(CityProperty, newCity);
} }
newCity.RangeOfInfluence = GetCityRangeOfInfluence(newCity);
return newCity; return newCity;
} }
IEnumerable<int> ChoosePoints(int number) List<City> CreateCities()
{ {
List<City> cities = new List<City>();
var vertices = new List<int>(); var vertices = new List<int>();
for (int i = 0; i < number; i++) int guard = MaxPlacementTries;
int createdCitiesCount = 0;
while (createdCitiesCount < MaxCitiesCount && guard-- > 0)
{ {
var randomLocation = _locationGraph.Vertices[_random.Next(1, _locationGraph.Vertices.Count())]; var randomLocation = _locationGraph.Vertices.Skip(1).RandomElement(_random);
var count = randomLocation.Sites.Count(); var randomSite = randomLocation.Sites.RandomElement(_random);
var randomPoint = randomLocation.Sites[_random.Next(0, count)];
vertices.Add(randomPoint.Index); if (cities.Any(c => Point.Dist(PointUtils.Mean(c.Sites.Select(s => s.Center)), randomSite.Center) < c.RangeOfInfluence))
continue;
cities.Add(CreateCity(randomSite.Index, (int)Math.Ceiling(CitiesSize * _random.Next(0, 30))));
guard = MaxPlacementTries;
createdCitiesCount++;
} }
return vertices; return cities;
}
public float GetCityRangeOfInfluence(City city)
{
return RangeOfInfluence*city.Sites.Count;
} }
public void Annotate(Map map) public void Annotate(Map map)
{ {
_basicGraph = map.Sites.Clone() as Graph<MapSite>; _basicGraph = map.Sites.Clone() as Graph<MapSite>;
_locationGraph = map.Metadata.GetProperty<Graph<Location>>(LandmassPass.MapLocationsProperty); _locationGraph = map.Metadata.GetProperty<Graph<Location>>(LandmassPass.MapLocationsProperty);
var cities = new List<City>(); var cities = CreateCities();
var locations = LocateCities();
foreach (var index in locations)
cities.Add(CreateCity(index, _random.Next(0, 10)));
map.Metadata.SetProperty(CitiesProperty, cities); map.Metadata.SetProperty(CitiesProperty, cities);
} }
} }

View File

@ -5,7 +5,7 @@ using Assets.Voronoi;
namespace Assets.Cities namespace Assets.Cities
{ {
public class City public class City : IHasMetadata
{ {
public List<MapSite> Sites { get; set; } = new List<MapSite>(); public List<MapSite> Sites { get; set; } = new List<MapSite>();
@ -15,6 +15,8 @@ namespace Assets.Cities
public List<CityField> Fields { get; set; } = new List<CityField>(); public List<CityField> Fields { get; set; } = new List<CityField>();
public List<(int, int)> Edges = new List<(int, int)>(); public List<(int, int)> Edges = new List<(int, int)>();
public Point Center { get; set; }
public float RangeOfInfluence { get; set; } = 0;
public City() public City()
{ {
@ -24,6 +26,7 @@ namespace Assets.Cities
{ {
Sites = sites; Sites = sites;
} }
public void AddSite(MapSite site) public void AddSite(MapSite site)
{ {
@ -38,5 +41,7 @@ namespace Assets.Cities
Edges = a.Union(b).Except(a.Intersect(b)).ToList(); Edges = a.Union(b).Except(a.Intersect(b)).ToList();
} }
public Metadata Metadata { get; } = new Metadata();
} }
} }

View File

@ -3,8 +3,17 @@ using Assets.Common;
namespace Assets.Cities namespace Assets.Cities
{ {
public enum FieldType
{
MainSquare,
Business,
Living
}
public class CityField public class CityField
{ {
public IList<Point> Boundary { get; set; } = new List<Point>(); public IList<Point> Boundary { get; set; } = new List<Point>();
public FieldType Type { get; set; }
public Point Center { get; set; }
} }
} }

View File

@ -20,7 +20,7 @@ namespace Assets
public class GraphGeneratorDebug public class GraphGeneratorDebug
{ {
public bool enabled = true; public bool enabled = true;
public bool displayPoints = true; public bool displayPoints = true;
public bool displayBoundary = true; public bool displayBoundary = true;
public bool displayVertices = true; public bool displayVertices = true;
@ -37,6 +37,7 @@ namespace Assets
public bool displayCityFields = true; public bool displayCityFields = true;
[NonSerialized] public float generationTime = 0.0f; [NonSerialized] public float generationTime = 0.0f;
public bool displayRangeOfInfluence = false;
} }
[Serializable] [Serializable]
@ -52,22 +53,30 @@ namespace Assets
{ {
[NonSerialized] public Map Map; [NonSerialized] public Map Map;
[NonSerialized] public Thread GenerationThread; [NonSerialized] public Thread GenerationThread;
public GraphGeneratorDebug debug; public GraphGeneratorDebug debug;
public Vector2 size = new Vector2(); public Vector2 size = new Vector2();
public List<LocationType> types = new List<LocationType>(); public List<LocationType> types = new List<LocationType>();
[Range(0f, 360f)] [Range(0f, 360f)]
public float minimumRoadAngle = 30f; public float minimumRoadAngle = 30f;
[Range(0f, 1f)]
public float businessCityFields = 0.3f;
[Range(0f, 4f)] [Range(0f, 4f)]
public float minimumNudgeDistance = 0.5f; public float minimumNudgeDistance = 0.5f;
[Range(0f, 4f)] [Range(0f, 4f)]
public float maximumNudgeDistance = 1f; public float maximumNudgeDistance = 1f;
[Range(0f, 4f)] [Range(0f, 4f)]
public float minimumRoadLength = 1f; public float minimumRoadLength = 1f;
public float rangeOfInfluence = .5f;
[Range(0f, 1f)]
public float citiesSize = .5f;
[Range(0, 50)]
public int citiesCount = 20;
[Range(2.0f, 64.0f)] [Range(2.0f, 64.0f)]
public float radius = 8; public float radius = 8;
public int seed = Environment.TickCount; public int seed = Environment.TickCount;
@ -80,17 +89,17 @@ namespace Assets
{ {
GenerationThread?.Abort(); GenerationThread?.Abort();
GenerationThread = new Thread(() => GenerationThread = new Thread(() =>
{ {
var generator = CreateMapGenerator(); var generator = CreateMapGenerator();
var result = generator.Generate(size.x, size.y); var result = generator.Generate(size.x, size.y);
lock (GetType()) lock (GetType())
{ {
Map = result; Map = result;
onDone(result); onDone(result);
} }
}); });
GenerationThread.Start(); GenerationThread.Start();
} }
@ -109,13 +118,19 @@ namespace Assets
var generator = new MapGenerator(new VoronoiGridGenerator(seed, new PoissonDiskSampler(radius) { Generator = new Random(seed) })); var generator = new MapGenerator(new VoronoiGridGenerator(seed, new PoissonDiskSampler(radius) { Generator = new Random(seed) }));
generator.AddAnnotationPass(new LandmassPass(types.Prepend(new LocationType { name = "Ocean", height = -1 }).Select(t => new Location { Type = t }), new Random(seed))); generator.AddAnnotationPass(new LandmassPass(types.Prepend(new LocationType { name = "Ocean", height = -1 }).Select(t => new Location { Type = t }), new Random(seed)));
generator.AddAnnotationPass(new LocateCitiesPass(new Random(seed))); generator.AddAnnotationPass(new LocateCitiesPass(new Random(seed))
{
MaxCitiesCount = citiesCount,
RangeOfInfluence = rangeOfInfluence,
CitiesSize = citiesSize
});
generator.AddAnnotationPass(new CityFieldsPass(new Random(seed)) generator.AddAnnotationPass(new CityFieldsPass(new Random(seed))
{ {
MinimumAngle = Mathf.Deg2Rad * minimumRoadAngle, MinimumAngle = Mathf.Deg2Rad * minimumRoadAngle,
MaxNudgeDistance = maximumNudgeDistance, MaxNudgeDistance = maximumNudgeDistance,
MinNudgeDistance = minimumNudgeDistance, MinNudgeDistance = minimumNudgeDistance,
MinimumRoadLength = minimumRoadLength MinimumRoadLength = minimumRoadLength,
BusinessCityFields = businessCityFields
}); });
return generator; return generator;
@ -125,7 +140,7 @@ namespace Assets
{ {
GenerationThread?.Abort(); GenerationThread?.Abort();
} }
private void DisplayGraphCities(IEnumerable<City> cities) private void DisplayGraphCities(IEnumerable<City> cities)
{ {
foreach (City city in cities) foreach (City city in cities)
@ -143,7 +158,7 @@ namespace Assets
void OnDrawGizmos() void OnDrawGizmos()
{ {
if (!debug.enabled || Map == null) return; if (!debug.enabled || Map == null) return;
if (debug.displayBoundary) if (debug.displayBoundary)
{ {
Gizmos.color = Color.gray; Gizmos.color = Color.gray;
@ -153,7 +168,7 @@ namespace Assets
Gizmos.DrawLine(new Vector3(size.x, 0, size.y), new Vector3(size.x, 0, 0)); Gizmos.DrawLine(new Vector3(size.x, 0, size.y), new Vector3(size.x, 0, 0));
Gizmos.DrawLine(new Vector3(size.x, 0, size.y), new Vector3(0, 0, size.y)); Gizmos.DrawLine(new Vector3(size.x, 0, size.y), new Vector3(0, 0, size.y));
} }
if (debug.displayPoints) if (debug.displayPoints)
{ {
Gizmos.color = Color.white; Gizmos.color = Color.white;
@ -177,47 +192,47 @@ namespace Assets
Gizmos.color = Color.white; Gizmos.color = Color.white;
DebugUtils.DisplayGraphEdges(Map.Boundaries); DebugUtils.DisplayGraphEdges(Map.Boundaries);
} }
Gizmos.color = Color.blue; Gizmos.color = Color.blue;
if (!Map.Metadata.HasProperty(LandmassPass.MapLocationsProperty)) return; if (!Map.Metadata.HasProperty(LandmassPass.MapLocationsProperty)) return;
var locations = Map.Metadata.GetProperty<Graph<Location>>(LandmassPass.MapLocationsProperty); var locations = Map.Metadata.GetProperty<Graph<Location>>(LandmassPass.MapLocationsProperty);
if (debug.displayLocationCells) if (debug.displayLocationCells)
{ {
var cells = Map.Sites.Vertices var cells = Map.Sites.Vertices
.Where(s => s.Metadata.HasProperty(LandmassPass.SiteLocationProperty)) .Where(s => s.Metadata.HasProperty(LandmassPass.SiteLocationProperty))
.Where(s => s.Metadata.GetProperty<Location>(LandmassPass.SiteLocationProperty).Type.name != "Ocean"); .Where(s => s.Metadata.GetProperty<Location>(LandmassPass.SiteLocationProperty).Type.name != "Ocean");
foreach (var site in cells) foreach (var site in cells)
{ {
var location = site.Metadata.GetProperty<Location>(LandmassPass.SiteLocationProperty); var location = site.Metadata.GetProperty<Location>(LandmassPass.SiteLocationProperty);
Gizmos.color = location.Type.color; Gizmos.color = location.Type.color;
Gizmos.DrawSphere(site.Center.ToVector3(), 2); Gizmos.DrawSphere(site.Center.ToVector3(), 2);
} }
} }
// //
// if (debug.displayLocations && _locationGraph != null) // if (debug.displayLocations && _locationGraph != null)
// { // {
// DisplayGraphEdges(_locationGraph.Morph(a => a.Item1)); // DisplayGraphEdges(_locationGraph.Morph(a => a.Item1));
// } // }
// //
// if (debug.displayLocationPoints) // if (debug.displayLocationPoints)
// { // {
// foreach (var location in _locations.Skip(1)) // foreach (var location in _locations.Skip(1))
// { // {
// Gizmos.color = location.Type.color; // Gizmos.color = location.Type.color;
// foreach (var point in location.BoundaryPoints) // foreach (var point in location.BoundaryPoints)
// { // {
// var v = VoronoiGenerator.Voronoi.Vertices[point].ToVector3(); // var v = VoronoiGenerator.Voronoi.Vertices[point].ToVector3();
// Gizmos.DrawSphere(v, 1); // Gizmos.DrawSphere(v, 1);
// if (debug.displayLabels) Handles.Label(v + Vector3.right, $"{point} at {v.x:F2}, {v.y:f2}"); // if (debug.displayLabels) Handles.Label(v + Vector3.right, $"{point} at {v.x:F2}, {v.y:f2}");
// } // }
// } // }
// } // }
if (debug.displayLocationEdges) if (debug.displayLocationEdges)
{ {
@ -230,15 +245,15 @@ namespace Assets
} }
} }
} }
if (debug.displayCities && Map.Metadata.HasProperty(LocateCitiesPass.CitiesProperty)) if (debug.displayCities && Map.Metadata.HasProperty(LocateCitiesPass.CitiesProperty))
{ {
Gizmos.color = Color.magenta; Gizmos.color = Color.magenta;
DisplayGraphCities(Map.Metadata.GetProperty<IEnumerable<City>>(LocateCitiesPass.CitiesProperty)); DisplayGraphCities(Map.Metadata.GetProperty<IEnumerable<City>>(LocateCitiesPass.CitiesProperty));
} }
var cities = Map.Metadata.GetProperty<List<City>>(LocateCitiesPass.CitiesProperty); var cities = Map.Metadata.GetProperty<List<City>>(LocateCitiesPass.CitiesProperty);
if (debug.displayFieldBoundaries) if (debug.displayFieldBoundaries)
{ {
Gizmos.color = Color.white; Gizmos.color = Color.white;
@ -261,19 +276,44 @@ namespace Assets
} }
} }
if (debug.displayRangeOfInfluence)
{
foreach (var city in cities)
{
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(PointUtils.Mean(city.Sites.Select(s => s.Center)).ToVector3(), city.RangeOfInfluence);
Gizmos.DrawSphere(PointUtils.Mean(city.Sites.Select(s => s.Center)).ToVector3(), 1);
}
}
if (debug.displayCityFields) if (debug.displayCityFields)
{ {
Gizmos.color = Color.green; Gizmos.color = Color.blue;
foreach (var city in cities) foreach (var city in cities)
{ {
foreach (var field in city.Fields) foreach (var field in city.Fields)
{ {
switch (field.Type)
{
case FieldType.Business:
Gizmos.color = Color.green;
break;
case FieldType.Living:
Gizmos.color = Color.yellow;
break;
case FieldType.MainSquare:
Gizmos.color = Color.red;
break;
default:
Gizmos.color = Color.blue;
break;
}
foreach (var (a, b) in field.Boundary.RotateRight().Zip(field.Boundary, (a, b) => (a, b))) foreach (var (a, b) in field.Boundary.RotateRight().Zip(field.Boundary, (a, b) => (a, b)))
Gizmos.DrawLine(a.ToVector3(), b.ToVector3()); Gizmos.DrawLine(a.ToVector3(), b.ToVector3());
foreach (var tuple in field.Boundary.Zip(PointUtils.CalculateNormals(field.Boundary), (a, b) => (Point: a, Normal: a + b))) foreach (var tuple in field.Boundary.Zip(PointUtils.CalculateNormals(field.Boundary), (a, b) => (Point: a, Normal: a + b)))
Gizmos.DrawLine(tuple.Point.ToVector3(), tuple.Normal.ToVector3()); Gizmos.DrawLine(tuple.Point.ToVector3(), tuple.Normal.ToVector3());
} }
} }
} }

View File

@ -3,7 +3,7 @@
--- !u!129 &1 --- !u!129 &1
PlayerSettings: PlayerSettings:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
serializedVersion: 17 serializedVersion: 18
productGUID: 59b609f943ea458cd81d6a9bda1ea716 productGUID: 59b609f943ea458cd81d6a9bda1ea716
AndroidProfiler: 0 AndroidProfiler: 0
AndroidFilterTouchesWhenObscured: 0 AndroidFilterTouchesWhenObscured: 0
@ -52,8 +52,8 @@ PlayerSettings:
m_StackTraceTypes: 010000000100000001000000010000000100000001000000 m_StackTraceTypes: 010000000100000001000000010000000100000001000000
iosShowActivityIndicatorOnLoading: -1 iosShowActivityIndicatorOnLoading: -1
androidShowActivityIndicatorOnLoading: -1 androidShowActivityIndicatorOnLoading: -1
iosAppInBackgroundBehavior: 0
displayResolutionDialog: 0 displayResolutionDialog: 0
iosUseCustomAppBackgroundBehavior: 0
iosAllowHTTPDownload: 1 iosAllowHTTPDownload: 1
allowedAutorotateToPortrait: 1 allowedAutorotateToPortrait: 1
allowedAutorotateToPortraitUpsideDown: 1 allowedAutorotateToPortraitUpsideDown: 1
@ -156,7 +156,6 @@ PlayerSettings:
protectGraphicsMemory: 0 protectGraphicsMemory: 0
enableFrameTimingStats: 0 enableFrameTimingStats: 0
useHDRDisplay: 0 useHDRDisplay: 0
D3DHDRBitDepth: 0
m_ColorGamuts: 00000000 m_ColorGamuts: 00000000
targetPixelDensity: 30 targetPixelDensity: 30
resolutionScalingMode: 0 resolutionScalingMode: 0
@ -597,6 +596,7 @@ PlayerSettings:
XboxOneAllowedProductIds: [] XboxOneAllowedProductIds: []
XboxOnePersistentLocalStorageSize: 0 XboxOnePersistentLocalStorageSize: 0
XboxOneXTitleMemory: 8 XboxOneXTitleMemory: 8
xboxOneScriptCompiler: 1
XboxOneOverrideIdentityName: XboxOneOverrideIdentityName:
vrEditorSettings: vrEditorSettings:
daydream: daydream:

View File

@ -1,2 +1,2 @@
m_EditorVersion: 2019.2.0f1 m_EditorVersion: 2019.3.0a8
m_EditorVersionWithRevision: 2019.2.0f1 (20c1667945cf) m_EditorVersionWithRevision: 2019.3.0a8 (8ea4afdbfa47)