Finished road generator
This commit is contained in:
parent
1304499b66
commit
54b833b620
@ -49,9 +49,9 @@
|
|||||||
<Compile Include="Assets\Standard Assets\Character Controllers\Sources\Scripts\MouseLook.cs" />
|
<Compile Include="Assets\Standard Assets\Character Controllers\Sources\Scripts\MouseLook.cs" />
|
||||||
<Compile Include="Assets\Standard Assets\Environment\Water (Basic)\Scripts\WaterBasic.cs" />
|
<Compile Include="Assets\Standard Assets\Environment\Water (Basic)\Scripts\WaterBasic.cs" />
|
||||||
<None Include="Assets\Data\Config\tergen.xml" />
|
<None Include="Assets\Data\Config\tergen.xml" />
|
||||||
<None Include="Assets\Data\Biomes\Mountain.xml" />
|
|
||||||
<None Include="Assets\Standard Assets\Environment\Water (Basic)\Shaders\FXWaterBasic.shader" />
|
<None Include="Assets\Standard Assets\Environment\Water (Basic)\Shaders\FXWaterBasic.shader" />
|
||||||
<None Include="Assets\Data\Biomes\Grassland.xml" />
|
<None Include="Assets\Data\Biomes\Grassland.xml" />
|
||||||
|
<None Include="Assets\Data\Biomes\Mountain.xml" />
|
||||||
<Reference Include="UnityEngine.UI">
|
<Reference Include="UnityEngine.UI">
|
||||||
<HintPath>C:/Program Files/Unity/Editor/Data/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll</HintPath>
|
<HintPath>C:/Program Files/Unity/Editor/Data/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
@ -49,9 +49,9 @@
|
|||||||
<Compile Include="Assets\Standard Assets\Character Controllers\Sources\Scripts\MouseLook.cs" />
|
<Compile Include="Assets\Standard Assets\Character Controllers\Sources\Scripts\MouseLook.cs" />
|
||||||
<Compile Include="Assets\Standard Assets\Environment\Water (Basic)\Scripts\WaterBasic.cs" />
|
<Compile Include="Assets\Standard Assets\Environment\Water (Basic)\Scripts\WaterBasic.cs" />
|
||||||
<None Include="Assets\Data\Config\tergen.xml" />
|
<None Include="Assets\Data\Config\tergen.xml" />
|
||||||
<None Include="Assets\Data\Biomes\Mountain.xml" />
|
|
||||||
<None Include="Assets\Standard Assets\Environment\Water (Basic)\Shaders\FXWaterBasic.shader" />
|
<None Include="Assets\Standard Assets\Environment\Water (Basic)\Shaders\FXWaterBasic.shader" />
|
||||||
<None Include="Assets\Data\Biomes\Grassland.xml" />
|
<None Include="Assets\Data\Biomes\Grassland.xml" />
|
||||||
|
<None Include="Assets\Data\Biomes\Mountain.xml" />
|
||||||
<Reference Include="UnityEngine.UI">
|
<Reference Include="UnityEngine.UI">
|
||||||
<HintPath>C:/Program Files/Unity/Editor/Data/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll</HintPath>
|
<HintPath>C:/Program Files/Unity/Editor/Data/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
@ -54,12 +54,15 @@
|
|||||||
<Compile Include="Assets\Scripts\Generator\TerrainGenerator.cs" />
|
<Compile Include="Assets\Scripts\Generator\TerrainGenerator.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Biome.cs" />
|
<Compile Include="Assets\Scripts\Model\Biome.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Config\TerrainGeneratorConfig.cs" />
|
<Compile Include="Assets\Scripts\Model\Config\TerrainGeneratorConfig.cs" />
|
||||||
|
<Compile Include="Assets\Scripts\Model\IPositionable.cs" />
|
||||||
|
<Compile Include="Assets\Scripts\Model\LineSegment.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Map.cs" />
|
<Compile Include="Assets\Scripts\Model\Map.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Point.cs" />
|
<Compile Include="Assets\Scripts\Model\Rectangle.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Road\RoadNetwork.cs" />
|
<Compile Include="Assets\Scripts\Model\Road\RoadNetwork.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Road\RoadNode.cs" />
|
<Compile Include="Assets\Scripts\Model\Road\RoadNode.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Road\RoadSegment.cs" />
|
<Compile Include="Assets\Scripts\Model\Road\RoadSegment.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Texture.cs" />
|
<Compile Include="Assets\Scripts\Model\Texture.cs" />
|
||||||
|
<Compile Include="Assets\Scripts\Model\Vector2.cs" />
|
||||||
<Compile Include="Assets\Scripts\Noise\NoiseGenerator.cs" />
|
<Compile Include="Assets\Scripts\Noise\NoiseGenerator.cs" />
|
||||||
<Compile Include="Assets\Scripts\Noise\PerlinNoiseGenerator.cs" />
|
<Compile Include="Assets\Scripts\Noise\PerlinNoiseGenerator.cs" />
|
||||||
<Compile Include="Assets\Scripts\Unity\InitializeScript.cs" />
|
<Compile Include="Assets\Scripts\Unity\InitializeScript.cs" />
|
||||||
@ -69,15 +72,16 @@
|
|||||||
<Compile Include="Assets\Scripts\Utils\ColorHelper.cs" />
|
<Compile Include="Assets\Scripts\Utils\ColorHelper.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\Expression.cs" />
|
<Compile Include="Assets\Scripts\Utils\Expression.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\Logger.cs" />
|
<Compile Include="Assets\Scripts\Utils\Logger.cs" />
|
||||||
|
<Compile Include="Assets\Scripts\Utils\QuadTree.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\RandomExtensions.cs" />
|
<Compile Include="Assets\Scripts\Utils\RandomExtensions.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\Range.cs" />
|
<Compile Include="Assets\Scripts\Utils\Range.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\SerializationHelper.cs" />
|
<Compile Include="Assets\Scripts\Utils\SerializationHelper.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\Task.cs" />
|
<Compile Include="Assets\Scripts\Utils\Task.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\Texture2DExtensions.cs" />
|
<Compile Include="Assets\Scripts\Utils\Texture2DExtensions.cs" />
|
||||||
<None Include="Assets\Data\Config\tergen.xml" />
|
<None Include="Assets\Data\Config\tergen.xml" />
|
||||||
<None Include="Assets\Data\Biomes\Mountain.xml" />
|
|
||||||
<None Include="Assets\Standard Assets\Environment\Water (Basic)\Shaders\FXWaterBasic.shader" />
|
<None Include="Assets\Standard Assets\Environment\Water (Basic)\Shaders\FXWaterBasic.shader" />
|
||||||
<None Include="Assets\Data\Biomes\Grassland.xml" />
|
<None Include="Assets\Data\Biomes\Grassland.xml" />
|
||||||
|
<None Include="Assets\Data\Biomes\Mountain.xml" />
|
||||||
<Reference Include="Assembly-UnityScript-firstpass">
|
<Reference Include="Assembly-UnityScript-firstpass">
|
||||||
<HintPath>C:/Users/Tibi/Google Drive/FacultateCY/$ Licenta/Game/Library/ScriptAssemblies/Assembly-UnityScript-firstpass.dll</HintPath>
|
<HintPath>C:/Users/Tibi/Google Drive/FacultateCY/$ Licenta/Game/Library/ScriptAssemblies/Assembly-UnityScript-firstpass.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
@ -54,12 +54,15 @@
|
|||||||
<Compile Include="Assets\Scripts\Generator\TerrainGenerator.cs" />
|
<Compile Include="Assets\Scripts\Generator\TerrainGenerator.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Biome.cs" />
|
<Compile Include="Assets\Scripts\Model\Biome.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Config\TerrainGeneratorConfig.cs" />
|
<Compile Include="Assets\Scripts\Model\Config\TerrainGeneratorConfig.cs" />
|
||||||
|
<Compile Include="Assets\Scripts\Model\IPositionable.cs" />
|
||||||
|
<Compile Include="Assets\Scripts\Model\LineSegment.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Map.cs" />
|
<Compile Include="Assets\Scripts\Model\Map.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Point.cs" />
|
<Compile Include="Assets\Scripts\Model\Rectangle.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Road\RoadNetwork.cs" />
|
<Compile Include="Assets\Scripts\Model\Road\RoadNetwork.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Road\RoadNode.cs" />
|
<Compile Include="Assets\Scripts\Model\Road\RoadNode.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Road\RoadSegment.cs" />
|
<Compile Include="Assets\Scripts\Model\Road\RoadSegment.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Texture.cs" />
|
<Compile Include="Assets\Scripts\Model\Texture.cs" />
|
||||||
|
<Compile Include="Assets\Scripts\Model\Vector2.cs" />
|
||||||
<Compile Include="Assets\Scripts\Noise\NoiseGenerator.cs" />
|
<Compile Include="Assets\Scripts\Noise\NoiseGenerator.cs" />
|
||||||
<Compile Include="Assets\Scripts\Noise\PerlinNoiseGenerator.cs" />
|
<Compile Include="Assets\Scripts\Noise\PerlinNoiseGenerator.cs" />
|
||||||
<Compile Include="Assets\Scripts\Unity\InitializeScript.cs" />
|
<Compile Include="Assets\Scripts\Unity\InitializeScript.cs" />
|
||||||
@ -69,15 +72,16 @@
|
|||||||
<Compile Include="Assets\Scripts\Utils\ColorHelper.cs" />
|
<Compile Include="Assets\Scripts\Utils\ColorHelper.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\Expression.cs" />
|
<Compile Include="Assets\Scripts\Utils\Expression.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\Logger.cs" />
|
<Compile Include="Assets\Scripts\Utils\Logger.cs" />
|
||||||
|
<Compile Include="Assets\Scripts\Utils\QuadTree.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\RandomExtensions.cs" />
|
<Compile Include="Assets\Scripts\Utils\RandomExtensions.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\Range.cs" />
|
<Compile Include="Assets\Scripts\Utils\Range.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\SerializationHelper.cs" />
|
<Compile Include="Assets\Scripts\Utils\SerializationHelper.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\Task.cs" />
|
<Compile Include="Assets\Scripts\Utils\Task.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\Texture2DExtensions.cs" />
|
<Compile Include="Assets\Scripts\Utils\Texture2DExtensions.cs" />
|
||||||
<None Include="Assets\Data\Config\tergen.xml" />
|
<None Include="Assets\Data\Config\tergen.xml" />
|
||||||
<None Include="Assets\Data\Biomes\Mountain.xml" />
|
|
||||||
<None Include="Assets\Standard Assets\Environment\Water (Basic)\Shaders\FXWaterBasic.shader" />
|
<None Include="Assets\Standard Assets\Environment\Water (Basic)\Shaders\FXWaterBasic.shader" />
|
||||||
<None Include="Assets\Data\Biomes\Grassland.xml" />
|
<None Include="Assets\Data\Biomes\Grassland.xml" />
|
||||||
|
<None Include="Assets\Data\Biomes\Mountain.xml" />
|
||||||
<Reference Include="UnityEngine.UI">
|
<Reference Include="UnityEngine.UI">
|
||||||
<HintPath>C:/Program Files/Unity/Editor/Data/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll</HintPath>
|
<HintPath>C:/Program Files/Unity/Editor/Data/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
@ -51,9 +51,9 @@
|
|||||||
<Compile Include="Assets\Standard Assets\Character Controllers\Sources\Scripts\FlyCam.js" />
|
<Compile Include="Assets\Standard Assets\Character Controllers\Sources\Scripts\FlyCam.js" />
|
||||||
<Compile Include="Assets\Standard Assets\Character Controllers\Sources\Scripts\PlatformInputController.js" />
|
<Compile Include="Assets\Standard Assets\Character Controllers\Sources\Scripts\PlatformInputController.js" />
|
||||||
<None Include="Assets\Data\Config\tergen.xml" />
|
<None Include="Assets\Data\Config\tergen.xml" />
|
||||||
<None Include="Assets\Data\Biomes\Mountain.xml" />
|
|
||||||
<None Include="Assets\Standard Assets\Environment\Water (Basic)\Shaders\FXWaterBasic.shader" />
|
<None Include="Assets\Standard Assets\Environment\Water (Basic)\Shaders\FXWaterBasic.shader" />
|
||||||
<None Include="Assets\Data\Biomes\Grassland.xml" />
|
<None Include="Assets\Data\Biomes\Grassland.xml" />
|
||||||
|
<None Include="Assets\Data\Biomes\Mountain.xml" />
|
||||||
<Reference Include="UnityEngine.UI">
|
<Reference Include="UnityEngine.UI">
|
||||||
<HintPath>C:/Program Files/Unity/Editor/Data/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll</HintPath>
|
<HintPath>C:/Program Files/Unity/Editor/Data/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
@ -51,9 +51,9 @@
|
|||||||
<Compile Include="Assets\Standard Assets\Character Controllers\Sources\Scripts\FlyCam.js" />
|
<Compile Include="Assets\Standard Assets\Character Controllers\Sources\Scripts\FlyCam.js" />
|
||||||
<Compile Include="Assets\Standard Assets\Character Controllers\Sources\Scripts\PlatformInputController.js" />
|
<Compile Include="Assets\Standard Assets\Character Controllers\Sources\Scripts\PlatformInputController.js" />
|
||||||
<None Include="Assets\Data\Config\tergen.xml" />
|
<None Include="Assets\Data\Config\tergen.xml" />
|
||||||
<None Include="Assets\Data\Biomes\Mountain.xml" />
|
|
||||||
<None Include="Assets\Standard Assets\Environment\Water (Basic)\Shaders\FXWaterBasic.shader" />
|
<None Include="Assets\Standard Assets\Environment\Water (Basic)\Shaders\FXWaterBasic.shader" />
|
||||||
<None Include="Assets\Data\Biomes\Grassland.xml" />
|
<None Include="Assets\Data\Biomes\Grassland.xml" />
|
||||||
|
<None Include="Assets\Data\Biomes\Mountain.xml" />
|
||||||
<Reference Include="UnityEngine.UI">
|
<Reference Include="UnityEngine.UI">
|
||||||
<HintPath>C:/Program Files/Unity/Editor/Data/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll</HintPath>
|
<HintPath>C:/Program Files/Unity/Editor/Data/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<biome>
|
<biome>
|
||||||
<name>Grassland</name>
|
<name>Grassland</name>
|
||||||
<height>100</height>
|
<height>100</height>
|
||||||
<moisture min=".1" max=".5"/>
|
<moisture min=".03" max=".3"/>
|
||||||
<vegetationDensity min=".2" max=".5" />
|
<vegetationDensity min=".2" max=".5" />
|
||||||
<textures>
|
<textures>
|
||||||
<texture src="grass" expr="0.5" />
|
<texture src="grass" expr="0.5" />
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 50d52558244dee444936bce1f2bd9e0a
|
guid: 04f446df0e76dde479e71408d721ffcc
|
||||||
|
timeCreated: 1432915085
|
||||||
|
licenseType: Free
|
||||||
TextScriptImporter:
|
TextScriptImporter:
|
||||||
userData:
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
@ -35,8 +35,6 @@ namespace TransportGame.Generator
|
|||||||
RoadGenerator roadGenerator = new RoadGenerator();
|
RoadGenerator roadGenerator = new RoadGenerator();
|
||||||
roadGenerator.Generate(map);
|
roadGenerator.Generate(map);
|
||||||
|
|
||||||
Logger.DumpMap(map, "withroads.map");
|
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using TransportGame.Model;
|
using TransportGame.Model;
|
||||||
using TransportGame.Noise;
|
using TransportGame.Noise;
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace TransportGame.Generator
|
namespace TransportGame.Generator
|
||||||
{
|
{
|
||||||
@ -14,9 +13,13 @@ namespace TransportGame.Generator
|
|||||||
|
|
||||||
public void Generate(Map map)
|
public void Generate(Map map)
|
||||||
{
|
{
|
||||||
|
// Generate range
|
||||||
|
float mp = (float)(map.Width * map.Height) / (1024 * 1024); // For 4k x 4k range should be around 900
|
||||||
|
map.PopulationCenterRange = mp * 155f / 5f + 1490f / 3f; // For 2k x 2k range should be around 600
|
||||||
|
|
||||||
// Generate a number of points
|
// Generate a number of points
|
||||||
int maxPoints = map.Width * map.Height / (1024 * 512);
|
int maxPoints = 16 * (int) Math.Sqrt(mp);
|
||||||
int points = random.Next(maxPoints / 4, maxPoints);
|
int points = random.Next(maxPoints / 2, maxPoints);
|
||||||
|
|
||||||
for (int i = 0; i < points; ++i)
|
for (int i = 0; i < points; ++i)
|
||||||
{
|
{
|
||||||
@ -24,12 +27,12 @@ namespace TransportGame.Generator
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
px = random.Next(map.Width);
|
px = random.Next(map.Width / 6, 5 * map.Width / 6);
|
||||||
py = random.Next(map.Height);
|
py = random.Next(map.Height / 6, 5 * map.Height / 6);
|
||||||
}
|
}
|
||||||
while (map.IsWater(px, py));
|
while (map.IsWater(px, py));
|
||||||
|
|
||||||
map.PopulationCenters.Add(new Point(px, py));
|
map.PopulationCenters.Add(new Vector2(px, py));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,141 +4,382 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using TransportGame.Model;
|
using TransportGame.Model;
|
||||||
using TransportGame.Model.Road;
|
using TransportGame.Model.Road;
|
||||||
using UnityEngine;
|
using TransportGame.Utils;
|
||||||
|
using Vector2 = TransportGame.Model.Vector2;
|
||||||
|
|
||||||
namespace TransportGame.Generator
|
namespace TransportGame.Generator
|
||||||
{
|
{
|
||||||
public class RoadGenerator
|
public class RoadGenerator
|
||||||
{
|
{
|
||||||
|
class RoadGeneratorSegment
|
||||||
|
{
|
||||||
|
public RoadNode Terminal1;
|
||||||
|
public Vector2 Terminal2Pos;
|
||||||
|
public RoadNode Terminal2;
|
||||||
|
public bool Highway;
|
||||||
|
public int Time;
|
||||||
|
|
||||||
|
public RoadGeneratorSegment(RoadNode term1, Vector2 term2pos, bool highway, int time = 0)
|
||||||
|
{
|
||||||
|
Terminal1 = term1;
|
||||||
|
Terminal2Pos = term2pos;
|
||||||
|
Highway = highway;
|
||||||
|
Time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string str = String.Format("(gensegment, {0}->", Terminal1);
|
||||||
|
|
||||||
|
if (Terminal2 == null)
|
||||||
|
str += Terminal2Pos.ToString();
|
||||||
|
else str += Terminal2.ToString();
|
||||||
|
|
||||||
|
str += ", ";
|
||||||
|
if (Highway)
|
||||||
|
str += "highway, ";
|
||||||
|
str += String.Format("time={0})", Time);
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QuadTree<RoadNode> qtree;
|
||||||
|
List<RoadGeneratorSegment> queue;
|
||||||
|
|
||||||
System.Random random = new System.Random();
|
System.Random random = new System.Random();
|
||||||
Map map;
|
Map map;
|
||||||
|
|
||||||
const int segmentCountLimit = 100;
|
const float HighwaySegmentLength = 60;
|
||||||
const int maxSegmentLength = 20;
|
const float DefaultBranchPopulationTreshold = 0.12f;
|
||||||
const int minSegmentLength = 1;
|
const float DefaultBranchProbability = 0.2f;
|
||||||
|
const float DefaultSegmentLength = 24;
|
||||||
|
const float SteepnessLimit = 10;
|
||||||
|
const float SlopeLimit = (float)Math.PI / 6;
|
||||||
|
const float RoadSegmentAngleLimit = (float)Math.PI / 4;
|
||||||
|
const float RoadSnapDistance = 19;
|
||||||
|
const float MinNodeDistance = 12;
|
||||||
|
const int MaximumRandomStraightAngle = 45; // in degrees
|
||||||
|
const int MaximumBranchAngleVariation = 12; // in degrees
|
||||||
|
const float HighwayBranchPopulationTreshold = .4f; // 0..1
|
||||||
|
const float HighwayBranchProbability = .01f;
|
||||||
|
const int HighwayBranchDelay = 3;
|
||||||
|
const int MaximumIntersectingRoads = 5;
|
||||||
|
|
||||||
public RoadGenerator()
|
public RoadGenerator()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Generate(Map map)
|
public void Initialize(Map map)
|
||||||
{
|
{
|
||||||
this.map = map;
|
this.map = map;
|
||||||
map.RoadNetwork = new RoadNetwork();
|
map.RoadNetwork = new RoadNetwork();
|
||||||
|
qtree = new QuadTree<RoadNode>(0, 0, map.Width, map.Height);
|
||||||
|
queue = new List<RoadGeneratorSegment>();
|
||||||
|
|
||||||
Queue<RoadNode> queue = new Queue<RoadNode>();
|
// Generate positions
|
||||||
RoadNode first = map.RoadNetwork.CreateNode();
|
Vector2 center = new Vector2(map.Width / 2, map.Height / 2);
|
||||||
queue.Enqueue(first);
|
int maxDistanceFromCenter = map.Width / 3;
|
||||||
|
|
||||||
// Set starting point
|
Vector2 p0, p1, p2; // p2 goes in opposite direction
|
||||||
if (map.PopulationCenters != null && map.PopulationCenters.Count > 0)
|
|
||||||
|
do
|
||||||
{
|
{
|
||||||
first.X = map.PopulationCenters.First().X;
|
// Generate point close to center of the map
|
||||||
first.Y = map.PopulationCenters.First().Y;
|
float gen_x = random.Next(-maxDistanceFromCenter, maxDistanceFromCenter) + random.NextSingle();
|
||||||
|
float gen_y = random.Next(-maxDistanceFromCenter, maxDistanceFromCenter) + random.NextSingle();
|
||||||
|
|
||||||
|
p0 = center + new Vector2(gen_x, gen_y);
|
||||||
|
|
||||||
|
// Generate a random direction
|
||||||
|
Vector2 dir = Vector2.FromDegrees(random.Next(360)) * (HighwaySegmentLength / 2);
|
||||||
|
p1 = p0 + dir;
|
||||||
|
p2 = p0 - dir;
|
||||||
|
|
||||||
|
} while (IsObstacle(p0) || IsObstacle(p1) || IsObstacle(p2));
|
||||||
|
|
||||||
|
// Logger.Info("Generated initial segment: {0} -> {1}", p0, p1);
|
||||||
|
// Logger.Info("Generated initial segment: {0} -> {1}", p0, p2);
|
||||||
|
|
||||||
|
// Create root node
|
||||||
|
var node0 = map.RoadNetwork.CreateNode(p0);
|
||||||
|
qtree.Add(node0);
|
||||||
|
|
||||||
|
// Logger.Info("Generated root node: {0}", node0);
|
||||||
|
|
||||||
|
// Create & enqueue segments
|
||||||
|
queue.Add(new RoadGeneratorSegment(node0, p1, true));
|
||||||
|
queue.Add(new RoadGeneratorSegment(node0, p2, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Step()
|
||||||
|
{
|
||||||
|
// Logger.Info(">>> BEGAN STEP <<<");
|
||||||
|
|
||||||
|
var segment = queue.OrderBy(x => x.Time).First();
|
||||||
|
queue.Remove(segment);
|
||||||
|
|
||||||
|
// Logger.Info("Dequeued segment {0}", segment);
|
||||||
|
|
||||||
|
// Check local constraints
|
||||||
|
if (CheckLocalConstraints(segment))
|
||||||
|
{
|
||||||
|
// Logger.Info("Local constraints check succeeded.");
|
||||||
|
RoadSegment createdSegment;
|
||||||
|
|
||||||
|
// Finish to create segment
|
||||||
|
if (segment.Terminal2 != null)
|
||||||
|
createdSegment = map.RoadNetwork.CreateArticulationSegment(segment.Terminal1, segment.Terminal2);
|
||||||
|
|
||||||
|
else
|
||||||
|
createdSegment = map.RoadNetwork.CreateArticulationSegment(segment.Terminal1, segment.Terminal2Pos);
|
||||||
|
|
||||||
|
qtree.Add(createdSegment.Terminal2);
|
||||||
|
createdSegment.LanesTo1 = createdSegment.LanesTo2 = (segment.Highway) ? 3 : 1;
|
||||||
|
|
||||||
|
// Use global goals to get new segments
|
||||||
|
foreach (var newSegment in GlobalGoals(createdSegment))
|
||||||
|
{
|
||||||
|
newSegment.Time += segment.Time + 1;
|
||||||
|
queue.Add(newSegment);
|
||||||
|
// Logger.Info("Added segment to queue: {0}", newSegment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
first.X = random.Next(map.Width);
|
// Logger.Info("Local constraints check failed!");
|
||||||
first.Y = random.Next(map.Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go through each node
|
|
||||||
for (int i = 0; i < segmentCountLimit && queue.Count > 0; i++)
|
|
||||||
{
|
|
||||||
RoadNode node = queue.Dequeue();
|
|
||||||
|
|
||||||
// Produce solutions based on global goals
|
|
||||||
foreach (var next in GlobalGoals(node))
|
|
||||||
{
|
|
||||||
if (CheckLocalConstraints(node, next))
|
|
||||||
{
|
|
||||||
// Next is a temporary node - create a node on the road network
|
|
||||||
var other = map.RoadNetwork.CreateNode();
|
|
||||||
other.X = next.X;
|
|
||||||
other.Y = next.Y;
|
|
||||||
|
|
||||||
// Create a segment
|
|
||||||
var segment = map.RoadNetwork.CreateArticulationSegment();
|
|
||||||
|
|
||||||
// Assign IDs
|
|
||||||
segment.Terminal1Id = node.Id;
|
|
||||||
segment.Terminal2Id = other.Id;
|
|
||||||
node.ArticulationSegmentIds.Add(segment.Id);
|
|
||||||
other.ArticulationSegmentIds.Add(segment.Id);
|
|
||||||
|
|
||||||
// Enqueue node
|
|
||||||
queue.Enqueue(other);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<RoadNode> GlobalGoals(RoadNode node)
|
private bool IsObstacle(Vector2 p)
|
||||||
{
|
{
|
||||||
// Goal #1 - connect population centers
|
return !map.IsInside(p.X, p.Y) || map.IsWater(p.X, p.Y) || map.GetSteepness(p.X, p.Y) > SteepnessLimit;
|
||||||
foreach (var popCenter in map.PopulationCenters.Skip(1))
|
}
|
||||||
{
|
|
||||||
// Get direction vector
|
|
||||||
float dx = popCenter.X - node.X;
|
|
||||||
float dy = popCenter.Y - node.Y;
|
|
||||||
|
|
||||||
// Ignore if too close to population center
|
public void Generate(Map map)
|
||||||
if (Math.Abs(dx) <= 1 && Math.Abs(dy) <= 1)
|
{
|
||||||
|
Initialize(map);
|
||||||
|
|
||||||
|
int iterationCount = (map.Width * map.Height) / 512;
|
||||||
|
|
||||||
|
for (int i = 0; i < iterationCount && queue.Count > 0; i++)
|
||||||
|
Step();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<RoadGeneratorSegment> GlobalGoals(RoadSegment segment)
|
||||||
|
{
|
||||||
|
Vector2 prevPos = segment.Terminal2.Position;
|
||||||
|
Vector2 dir = (segment.Terminal2.Position - segment.Terminal1.Position).Normalized;
|
||||||
|
bool highway = (segment.LanesTo1 >= 3);
|
||||||
|
bool highwayBranched = false;
|
||||||
|
|
||||||
|
// Logger.Info("> Computing global goals. prevPos={0}, dir={1}, highway={2}", prevPos, dir, highway);
|
||||||
|
|
||||||
|
// Going straight
|
||||||
|
Vector2 straight = prevPos + dir * ((highway) ? HighwaySegmentLength : DefaultSegmentLength);
|
||||||
|
float straightPopulation = map.GetPopulation(straight);
|
||||||
|
|
||||||
|
// Logger.Info("> Straight={0} StraightPopulation={1}", straight, straightPopulation);
|
||||||
|
|
||||||
|
// Highways...
|
||||||
|
if (highway)
|
||||||
|
{
|
||||||
|
// Logger.Info("> Highway case:");
|
||||||
|
|
||||||
|
Vector2 randomStraight = prevPos + HighwaySegmentLength * dir.RotateDeg(random.Next(-MaximumRandomStraightAngle, MaximumRandomStraightAngle));
|
||||||
|
float randomPopulation = map.GetPopulation(randomStraight);
|
||||||
|
|
||||||
|
// Logger.Info("> RandomStraight={0} RandomPopulation={1}", randomStraight, randomPopulation);
|
||||||
|
|
||||||
|
if (randomPopulation > straightPopulation)
|
||||||
|
{
|
||||||
|
// Logger.Info("> Yielding random straight vector.");
|
||||||
|
yield return new RoadGeneratorSegment(segment.Terminal2, randomStraight, highway);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Logger.Info("> Yielding straight vector.");
|
||||||
|
yield return new RoadGeneratorSegment(segment.Terminal2, straight, highway);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Branch highway
|
||||||
|
if (Math.Max(straightPopulation, randomPopulation) > HighwayBranchPopulationTreshold)
|
||||||
|
{
|
||||||
|
// Logger.Info("> Above treshold. Branching...");
|
||||||
|
if (random.NextSingle() < HighwayBranchProbability)
|
||||||
|
{
|
||||||
|
Vector2 leftBranch = prevPos + HighwaySegmentLength * dir.RotateDeg(-90 + random.Next(-MaximumBranchAngleVariation, MaximumBranchAngleVariation));
|
||||||
|
yield return new RoadGeneratorSegment(segment.Terminal2, leftBranch, highway, HighwayBranchDelay);
|
||||||
|
|
||||||
|
highwayBranched = true;
|
||||||
|
// Logger.Info("> Branch to the left: {0}", leftBranch);
|
||||||
|
}
|
||||||
|
if (random.NextSingle() < HighwayBranchProbability)
|
||||||
|
{
|
||||||
|
Vector2 rightBranch = prevPos + HighwaySegmentLength * dir.RotateDeg(90 + random.Next(-MaximumBranchAngleVariation, MaximumBranchAngleVariation));
|
||||||
|
yield return new RoadGeneratorSegment(segment.Terminal2, rightBranch, highway, HighwayBranchDelay);
|
||||||
|
|
||||||
|
highwayBranched = true;
|
||||||
|
// Logger.Info("> Branch to the right: {0}", rightBranch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't allow more branches
|
||||||
|
if (highwayBranched)
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (random.NextSingle() < straightPopulation)
|
||||||
|
{
|
||||||
|
// Logger.Info("> Not highway. Yielding straight vector.");
|
||||||
|
yield return new RoadGeneratorSegment(segment.Terminal2, straight, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Branch normal road
|
||||||
|
if (straightPopulation > DefaultBranchPopulationTreshold)
|
||||||
|
{
|
||||||
|
// Logger.Info("Straight population above branch treshold. Branching...");
|
||||||
|
if (random.NextSingle() < DefaultBranchProbability * straightPopulation)
|
||||||
|
{
|
||||||
|
Vector2 leftBranch = prevPos + HighwaySegmentLength * dir.RotateDeg(-90 + random.Next(-MaximumBranchAngleVariation, MaximumBranchAngleVariation));
|
||||||
|
yield return new RoadGeneratorSegment(segment.Terminal2, leftBranch, false, (highway) ? HighwayBranchDelay : 0);
|
||||||
|
|
||||||
|
// Logger.Info("> Branch to the left: {0}", leftBranch);
|
||||||
|
}
|
||||||
|
if (random.NextSingle() < DefaultBranchProbability * straightPopulation)
|
||||||
|
{
|
||||||
|
Vector2 rightBranch = prevPos + HighwaySegmentLength * dir.RotateDeg(90 + random.Next(-MaximumBranchAngleVariation, MaximumBranchAngleVariation));
|
||||||
|
yield return new RoadGeneratorSegment(segment.Terminal2, rightBranch, false, (highway) ? HighwayBranchDelay : 0);
|
||||||
|
|
||||||
|
// Logger.Info("> Branch to the right: {0}", rightBranch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckLocalConstraints(RoadGeneratorSegment segment)
|
||||||
|
{
|
||||||
|
// Logger.Info("Checking local constraints...");
|
||||||
|
|
||||||
|
// Constraint #1: check for obstacles
|
||||||
|
if (IsObstacle(segment.Terminal2Pos))
|
||||||
|
{
|
||||||
|
// Logger.Info("Obstacle.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constraint #2: slope
|
||||||
|
float segmentLength = (segment.Highway) ? HighwaySegmentLength : DefaultSegmentLength;
|
||||||
|
float levelDiff = map.GetHeight((int)segment.Terminal1.X, (int)segment.Terminal1.Y) -
|
||||||
|
map.GetHeight((int)segment.Terminal2Pos.X, (int)segment.Terminal2Pos.Y);
|
||||||
|
float sinSlope = Math.Abs(levelDiff) / segmentLength;
|
||||||
|
|
||||||
|
// Logger.Info("Level difference is {0}, slope is (rads) {1}", levelDiff, Math.Asin(sinSlope));
|
||||||
|
|
||||||
|
if (Math.Asin(sinSlope) > SlopeLimit)
|
||||||
|
{
|
||||||
|
// Logger.Info("Slope too big!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constraint #3: Number of intersecting roads
|
||||||
|
if (segment.Terminal1.ArticulationSegmentIds.Count > MaximumIntersectingRoads)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Constraint #4: intersections & snapping
|
||||||
|
Rectangle queryArea = new Rectangle(
|
||||||
|
Math.Min(segment.Terminal1.X, segment.Terminal2Pos.X) - 3 * HighwaySegmentLength,
|
||||||
|
Math.Min(segment.Terminal1.Y, segment.Terminal2Pos.Y) - 3 * HighwaySegmentLength,
|
||||||
|
Math.Max(segment.Terminal1.X, segment.Terminal2Pos.X) + 3 * HighwaySegmentLength,
|
||||||
|
Math.Max(segment.Terminal1.Y, segment.Terminal2Pos.Y) + 3 * HighwaySegmentLength);
|
||||||
|
|
||||||
|
// Logger.Info("Searching area {0} for intersecting segments.", queryArea);
|
||||||
|
|
||||||
|
IEnumerable<int> segmentIds = Enumerable.Empty<int>();
|
||||||
|
|
||||||
|
// Look for nearby segments
|
||||||
|
foreach (var node in qtree.Query(queryArea))
|
||||||
|
{
|
||||||
|
// Logger.Info("Found node: {0}", node);
|
||||||
|
if (node == segment.Terminal1)
|
||||||
|
{
|
||||||
|
// Logger.Info("Node is originating node. Will ignore.");
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Calculate length of direction vector (we need to normalize it)
|
|
||||||
float dlen = Mathf.Sqrt(dx * dx + dy * dy);
|
|
||||||
|
|
||||||
// Length of segment
|
|
||||||
int length = random.Next(minSegmentLength, maxSegmentLength);
|
|
||||||
|
|
||||||
// Calculate coordinates
|
|
||||||
yield return new RoadNode()
|
|
||||||
{
|
|
||||||
X = node.X + length * dx / dlen,
|
|
||||||
Y = node.Y + length * dy / dlen
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Goal #2 - random segments depending on how populated is area - max 25% chance
|
// Too close to another node in the area
|
||||||
if (random.NextDouble() < map.GetPopulation(Convert.ToInt32(node.X), Convert.ToInt32(node.Y)) * 4)
|
if ((node.Position - segment.Terminal2Pos).LengthSq < MinNodeDistance * MinNodeDistance)
|
||||||
{
|
return false;
|
||||||
// Generate direction vector
|
|
||||||
float dx = Convert.ToSingle(random.NextDouble()) * 2 - 1;
|
|
||||||
float dy = Convert.ToSingle(random.NextDouble()) * 2 - 1;
|
|
||||||
|
|
||||||
int length = random.Next(minSegmentLength, maxSegmentLength);
|
segmentIds = segmentIds.Concat(node.ArticulationSegmentIds);
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate coordinates
|
// Filter & sort the segments by distance
|
||||||
yield return new RoadNode()
|
segmentIds = segmentIds.Distinct().OrderBy(id =>
|
||||||
{
|
{
|
||||||
X = node.X + dx * length,
|
var seg = map.RoadNetwork.ArticulationSegments[id];
|
||||||
Y = node.Y + dy * length
|
var line = new LineSegment(seg.Terminal1.Position, seg.Terminal2.Position);
|
||||||
};
|
return LineSegment.Distance(line, segment.Terminal2Pos);
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (var segmentId in segmentIds)
|
||||||
|
{
|
||||||
|
var other = map.RoadNetwork.ArticulationSegments[segmentId];
|
||||||
|
var line1 = new LineSegment(segment.Terminal1.Position, segment.Terminal2Pos);
|
||||||
|
var line2 = new LineSegment(other.Terminal1.Position, other.Terminal2.Position);
|
||||||
|
|
||||||
|
// Logger.Info("Found segment: {0}. Will test intersection between segments {0} and {1}", other, line1, line2);
|
||||||
|
|
||||||
|
Vector2? inters = LineSegment.Intersect(line1, line2);
|
||||||
|
|
||||||
|
// Case #1: there is an intersection with another segment. We cut the rest of the segment
|
||||||
|
if (inters.HasValue && inters.Value != segment.Terminal1.Position)
|
||||||
|
{
|
||||||
|
// Logger.Info("Found intersection point: {0}", inters);
|
||||||
|
|
||||||
|
// Check angle between segments
|
||||||
|
float cos = Vector2.Dot((line1.P1 - line1.P0).Normalized, (line2.P1 - line2.P0).Normalized);
|
||||||
|
if (Math.Abs(Math.Acos(cos)) < RoadSegmentAngleLimit)
|
||||||
|
{
|
||||||
|
// Logger.Info("Angle between segments is too small ({0} rads)", Math.Abs(Math.Acos(cos)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split segment
|
||||||
|
var newNode = map.RoadNetwork.SplitArticulationSegment(other, inters.Value);
|
||||||
|
segment.Terminal2Pos = inters.Value;
|
||||||
|
segment.Terminal2 = newNode;
|
||||||
|
// Logger.Info("Performed split in point: {0}", newNode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else // Logger.Info("Does not intersect.");
|
||||||
|
|
||||||
|
// Case #2: no intersection, but the point is close enough to an existing intersection
|
||||||
|
if ((segment.Terminal2Pos - other.Terminal2.Position).LengthSq <= RoadSnapDistance * RoadSnapDistance)
|
||||||
|
{
|
||||||
|
// Check angle between intersecting segments
|
||||||
|
foreach (var intersSeg in other.Terminal2.ArticulationSegments)
|
||||||
|
{
|
||||||
|
float cos = Vector2.Dot((line1.P1 - line1.P0).Normalized, (intersSeg.Terminal2.Position - intersSeg.Terminal1.Position).Normalized);
|
||||||
|
if (Math.Abs(Math.Acos(cos)) < RoadSegmentAngleLimit)
|
||||||
|
{
|
||||||
|
// Logger.Info("Angle between segments is too small ({0} rads)", Math.Abs(Math.Acos(cos)));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CheckLocalConstraints(RoadNode first, RoadNode second)
|
// Logger.Info("Point is close to existing intersection: {0}, will snap.", other.Terminal2);
|
||||||
{
|
segment.Terminal2Pos = other.Terminal2.Position;
|
||||||
// Make sure point is inside map
|
segment.Terminal2 = other.Terminal2;
|
||||||
if (!map.IsInside(Convert.ToInt32(second.X), Convert.ToInt32(second.Y)))
|
return true;
|
||||||
return false;
|
}
|
||||||
|
|
||||||
// Cannot build on water
|
//// TODO: Case #3: the point is close enough to an existing road segment
|
||||||
if (map.IsWater(Convert.ToInt32(second.X), Convert.ToInt32(second.Y)))
|
//float dist = LineSegment.Distance(line2, segment.Terminal2Pos);
|
||||||
return false;
|
//if (dist < RoadSnapDistance)
|
||||||
|
//{
|
||||||
// Check steepness
|
// float proj0 = (float)Math.Sqrt((line2.P0 - segment.Terminal2Pos).LengthSq - dist * dist);
|
||||||
int mix = Convert.ToInt32(Math.Min(first.X, second.X));
|
// float percent = proj0 /
|
||||||
int max = Convert.ToInt32(Math.Max(first.X, second.X));
|
//}
|
||||||
int miy = Convert.ToInt32(Math.Min(first.Y, second.Y));
|
|
||||||
int may = Convert.ToInt32(Math.Max(first.Y, second.Y));
|
|
||||||
|
|
||||||
for (int x = mix; x <= max; x++)
|
|
||||||
for (int y = miy; y <= may; y++)
|
|
||||||
{
|
|
||||||
if (map.GetSteepness(x, y) > 1)
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -73,7 +73,9 @@ namespace TransportGame.Model
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[XmlArray("populationCenters")]
|
[XmlArray("populationCenters")]
|
||||||
[XmlArrayItem("center")]
|
[XmlArrayItem("center")]
|
||||||
public List<Point> PopulationCenters { get; set; }
|
public List<Vector2> PopulationCenters { get; set; }
|
||||||
|
|
||||||
|
public float PopulationCenterRange { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the articulation road network
|
/// Gets or sets the articulation road network
|
||||||
@ -93,7 +95,7 @@ namespace TransportGame.Model
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
public Map()
|
public Map()
|
||||||
{
|
{
|
||||||
PopulationCenters = new List<Point>();
|
PopulationCenters = new List<Vector2>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -104,7 +106,7 @@ namespace TransportGame.Model
|
|||||||
public Map(int width, int height)
|
public Map(int width, int height)
|
||||||
{
|
{
|
||||||
heightmap = new float[width, height];
|
heightmap = new float[width, height];
|
||||||
PopulationCenters = new List<Point>();
|
PopulationCenters = new List<Vector2>();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -137,9 +139,19 @@ namespace TransportGame.Model
|
|||||||
/// <param name="x">X</param>
|
/// <param name="x">X</param>
|
||||||
/// <param name="y">Y</param>
|
/// <param name="y">Y</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool IsWater(int x, int y)
|
public bool IsWater(float x, float y)
|
||||||
{
|
{
|
||||||
return GetHeight(x, y) <= WaterLevel;
|
return GetHeight((int)x, (int)y) <= WaterLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if specified cell is a water cell
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="p">Position vector</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool IsWater(Vector2 p)
|
||||||
|
{
|
||||||
|
return IsWater(p.X, p.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -148,11 +160,21 @@ namespace TransportGame.Model
|
|||||||
/// <param name="x">X</param>
|
/// <param name="x">X</param>
|
||||||
/// <param name="y">Y</param>
|
/// <param name="y">Y</param>
|
||||||
/// <returns>True if coordinates are inside the map</returns>
|
/// <returns>True if coordinates are inside the map</returns>
|
||||||
public bool IsInside(int x, int y)
|
public bool IsInside(float x, float y)
|
||||||
{
|
{
|
||||||
return x >= 0 && y >= 0 && x < Width && y < Height;
|
return x >= 0 && y >= 0 && x < Width && y < Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if given coordinates is inside the map
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="p">Position vector</param>
|
||||||
|
/// <returns>True if coordinates are inside the map</returns>
|
||||||
|
public bool IsInside(Vector2 p)
|
||||||
|
{
|
||||||
|
return IsInside(p.X, p.Y);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets steepness in specified point
|
/// Gets steepness in specified point
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -170,27 +192,56 @@ namespace TransportGame.Model
|
|||||||
return dx * dx + dy * dy;
|
return dx * dx + dy * dy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets steepness in specified point
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">X</param>
|
||||||
|
/// <param name="y">Y</param>
|
||||||
|
/// <returns>Steepness</returns>
|
||||||
|
public float GetSteepness(float x, float y)
|
||||||
|
{
|
||||||
|
return GetSteepness((int)x, (int)y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets steepness in specified point
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pos">Position</param>
|
||||||
|
/// <returns>Steepness</returns>
|
||||||
|
public float GetSteepness(Vector2 pos)
|
||||||
|
{
|
||||||
|
return GetSteepness((int)pos.X, (int)pos.Y);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets population using terrain coordinates
|
/// Gets population using terrain coordinates
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="x">X</param>
|
/// <param name="x">X</param>
|
||||||
/// <param name="y">Y</param>
|
/// <param name="y">Y</param>
|
||||||
/// <returns>Population</returns>
|
/// <returns>Population</returns>
|
||||||
public float GetPopulation(int x, int y)
|
public float GetPopulation(float x, float y)
|
||||||
{
|
{
|
||||||
const int maxDistance = 400;
|
return GetPopulation(new Vector2(x, y));
|
||||||
float value = 0;
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets population using terrain coordinates
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="p">Position</param>
|
||||||
|
/// <returns>Population</returns>
|
||||||
|
public float GetPopulation(Vector2 p)
|
||||||
|
{
|
||||||
|
float value = 0.05f;
|
||||||
|
|
||||||
foreach (var point in PopulationCenters)
|
foreach (var point in PopulationCenters)
|
||||||
{
|
{
|
||||||
int x1 = x - point.X;
|
Vector2 diff = p - point;
|
||||||
int y1 = y - point.Y;
|
float dist = diff.LengthSq;
|
||||||
|
|
||||||
int dist = x1 * x1 + y1 * y1;
|
if (dist < PopulationCenterRange * PopulationCenterRange)
|
||||||
if (dist < maxDistance * maxDistance)
|
|
||||||
{
|
{
|
||||||
float influence = 1 - (float)dist / (float)(maxDistance * maxDistance);
|
float influence = 1 - (float)dist / (float)(PopulationCenterRange * PopulationCenterRange);
|
||||||
influence = Mathf.Pow(influence, 3); // Ease
|
influence = Mathf.Pow(influence, 6) * 0.7f; // Ease
|
||||||
value = Mathf.Clamp01(value + influence);
|
value = Mathf.Clamp01(value + influence);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
|
using TransportGame.Utils;
|
||||||
|
|
||||||
namespace TransportGame.Model.Road
|
namespace TransportGame.Model.Road
|
||||||
{
|
{
|
||||||
@ -12,20 +13,19 @@ namespace TransportGame.Model.Road
|
|||||||
private int lastNodeId = -1, lastSegmentId = -1;
|
private int lastNodeId = -1, lastSegmentId = -1;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the road nodes
|
/// Gets the road nodes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[XmlIgnore]
|
[XmlIgnore]
|
||||||
public Dictionary<int, RoadNode> Nodes { get; private set; }
|
public Dictionary<int, RoadNode> Nodes { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the road segments for the articulation graph
|
/// Gets the road segments for the articulation graph
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[XmlIgnore]
|
[XmlIgnore]
|
||||||
public Dictionary<int, RoadSegment> ArticulationSegments { get; private set; }
|
public Dictionary<int, RoadSegment> ArticulationSegments { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the road segments for the intersection graph
|
/// Gets the road segments for the intersection graph
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[XmlIgnore]
|
[XmlIgnore]
|
||||||
public Dictionary<int, RoadSegment> IntersectionSegments { get; private set; }
|
public Dictionary<int, RoadSegment> IntersectionSegments { get; private set; }
|
||||||
@ -44,9 +44,12 @@ namespace TransportGame.Model.Road
|
|||||||
{
|
{
|
||||||
Nodes.Clear();
|
Nodes.Clear();
|
||||||
foreach (var node in value)
|
foreach (var node in value)
|
||||||
|
{
|
||||||
|
node.ParentNetwork = this;
|
||||||
Nodes.Add(node.Id, node);
|
Nodes.Add(node.Id, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the segments
|
/// Gets or sets the segments
|
||||||
@ -62,9 +65,12 @@ namespace TransportGame.Model.Road
|
|||||||
{
|
{
|
||||||
ArticulationSegments.Clear();
|
ArticulationSegments.Clear();
|
||||||
foreach (var segment in value)
|
foreach (var segment in value)
|
||||||
|
{
|
||||||
|
segment.ParentNetwork = this;
|
||||||
ArticulationSegments.Add(segment.Id, segment);
|
ArticulationSegments.Add(segment.Id, segment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the segments
|
/// Gets or sets the segments
|
||||||
@ -80,9 +86,12 @@ namespace TransportGame.Model.Road
|
|||||||
{
|
{
|
||||||
ArticulationSegments.Clear();
|
ArticulationSegments.Clear();
|
||||||
foreach (var segment in value)
|
foreach (var segment in value)
|
||||||
|
{
|
||||||
|
segment.ParentNetwork = this;
|
||||||
ArticulationSegments.Add(segment.Id, segment);
|
ArticulationSegments.Add(segment.Id, segment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes the road network
|
/// Initializes the road network
|
||||||
@ -97,8 +106,9 @@ namespace TransportGame.Model.Road
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a node and returns it
|
/// Creates a node and returns it
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Created node</returns>
|
/// <param name="pos">Position</param>
|
||||||
public RoadNode CreateNode()
|
/// <returns></returns>
|
||||||
|
public RoadNode CreateNode(Vector2 pos)
|
||||||
{
|
{
|
||||||
// Skip IDs that already exist
|
// Skip IDs that already exist
|
||||||
while (Nodes.ContainsKey(++lastNodeId)) ;
|
while (Nodes.ContainsKey(++lastNodeId)) ;
|
||||||
@ -107,18 +117,39 @@ namespace TransportGame.Model.Road
|
|||||||
RoadNode node = new RoadNode()
|
RoadNode node = new RoadNode()
|
||||||
{
|
{
|
||||||
Id = lastNodeId,
|
Id = lastNodeId,
|
||||||
ParentNetwork = this
|
ParentNetwork = this,
|
||||||
|
Position = pos
|
||||||
};
|
};
|
||||||
|
|
||||||
Nodes.Add(node.Id, node);
|
Nodes.Add(node.Id, node);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a node and returns it
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Created node</returns>
|
||||||
|
public RoadNode CreateNode()
|
||||||
|
{
|
||||||
|
return CreateNode(Vector2.Zero);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a segment and returns it
|
/// Creates a segment and returns it
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Created segment</returns>
|
/// <returns>Created segment</returns>
|
||||||
public RoadSegment CreateArticulationSegment()
|
public RoadSegment CreateArticulationSegment()
|
||||||
|
{
|
||||||
|
return CreateArticulationSegment(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a segment and returns it
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="term1">First terminal</param>
|
||||||
|
/// <param name="term2">Second terminal</param>
|
||||||
|
/// <returns>Created segment</returns>
|
||||||
|
public RoadSegment CreateArticulationSegment(RoadNode term1, RoadNode term2)
|
||||||
{
|
{
|
||||||
// Skip IDs that already exist
|
// Skip IDs that already exist
|
||||||
while (ArticulationSegments.ContainsKey(++lastSegmentId)) ;
|
while (ArticulationSegments.ContainsKey(++lastSegmentId)) ;
|
||||||
@ -127,13 +158,59 @@ namespace TransportGame.Model.Road
|
|||||||
RoadSegment segment = new RoadSegment()
|
RoadSegment segment = new RoadSegment()
|
||||||
{
|
{
|
||||||
Id = lastSegmentId,
|
Id = lastSegmentId,
|
||||||
ParentNetwork = this
|
ParentNetwork = this,
|
||||||
|
Terminal1 = term1,
|
||||||
|
Terminal2 = term2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Set links
|
||||||
|
if (term1 != null)
|
||||||
|
term1.ArticulationSegmentIds.Add(segment.Id);
|
||||||
|
|
||||||
|
if (term2 != null)
|
||||||
|
term2.ArticulationSegmentIds.Add(segment.Id);
|
||||||
|
|
||||||
ArticulationSegments.Add(segment.Id, segment);
|
ArticulationSegments.Add(segment.Id, segment);
|
||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an articulation segment
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="term1">First terminal</param>
|
||||||
|
/// <param name="term2pos">Position of second terminal</param>
|
||||||
|
/// <returns>Road segment</returns>
|
||||||
|
public RoadSegment CreateArticulationSegment(RoadNode term1, Vector2 term2pos)
|
||||||
|
{
|
||||||
|
var term2 = CreateNode(term2pos);
|
||||||
|
return CreateArticulationSegment(term1, term2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an articulation segment
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="term1pos">Position of first terminal</param>
|
||||||
|
/// <param name="term2">Second terminal</param>
|
||||||
|
/// <returns>Road segment</returns>
|
||||||
|
public RoadSegment CreateArticulationSegment(Vector2 term1pos, RoadNode term2)
|
||||||
|
{
|
||||||
|
var term1 = CreateNode(term1pos);
|
||||||
|
return CreateArticulationSegment(term1, term2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an articulation segment
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="term1pos">Position of first terminal</param>
|
||||||
|
/// <param name="term2pos">Position of second terminal</param>
|
||||||
|
/// <returns>Road segment</returns>
|
||||||
|
public RoadSegment CreateArticulationSegment(Vector2 term1pos, Vector2 term2pos)
|
||||||
|
{
|
||||||
|
var term1 = CreateNode(term1pos);
|
||||||
|
var term2 = CreateNode(term2pos);
|
||||||
|
return CreateArticulationSegment(term1, term2);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a segment and returns it
|
/// Creates a segment and returns it
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -153,5 +230,35 @@ namespace TransportGame.Model.Road
|
|||||||
IntersectionSegments.Add(segment.Id, segment);
|
IntersectionSegments.Add(segment.Id, segment);
|
||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Splits an articulation segment in two segments
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="segment"></param>
|
||||||
|
/// <param name="point"></param>
|
||||||
|
/// <returns>Newly created road node</returns>
|
||||||
|
public RoadNode SplitArticulationSegment(RoadSegment segment, Vector2 point)
|
||||||
|
{
|
||||||
|
// Get current terminals
|
||||||
|
var term1 = segment.Terminal1;
|
||||||
|
var term2 = segment.Terminal2;
|
||||||
|
int l1 = segment.LanesTo1, l2 = segment.LanesTo2;
|
||||||
|
|
||||||
|
// Create new terminal
|
||||||
|
var newTerm = CreateNode(point);
|
||||||
|
|
||||||
|
// Delete exinsting segment
|
||||||
|
term1.ArticulationSegmentIds.Remove(segment.Id);
|
||||||
|
term2.ArticulationSegmentIds.Remove(segment.Id);
|
||||||
|
ArticulationSegments.Remove(segment.Id);
|
||||||
|
|
||||||
|
// Create split segments
|
||||||
|
var seg1 = CreateArticulationSegment(term1, newTerm);
|
||||||
|
var seg2 = CreateArticulationSegment(newTerm, term2);
|
||||||
|
seg1.LanesTo1 = seg2.LanesTo1 = l1;
|
||||||
|
seg1.LanesTo2 = seg2.LanesTo2 = l2;
|
||||||
|
|
||||||
|
return newTerm;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ namespace TransportGame.Model.Road
|
|||||||
/// Road node
|
/// Road node
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[XmlRoot("node")]
|
[XmlRoot("node")]
|
||||||
public class RoadNode
|
public class RoadNode : IPositionable
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a unique identifier for this node
|
/// Gets or sets a unique identifier for this node
|
||||||
@ -63,7 +63,7 @@ namespace TransportGame.Model.Road
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the adjacent setments
|
/// Gets the adjacent segments
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[XmlIgnore]
|
[XmlIgnore]
|
||||||
public IEnumerable<RoadSegment> Segments
|
public IEnumerable<RoadSegment> Segments
|
||||||
@ -82,5 +82,27 @@ namespace TransportGame.Model.Road
|
|||||||
ArticulationSegmentIds = new List<int>();
|
ArticulationSegmentIds = new List<int>();
|
||||||
IntersectionSegmentIds = new List<int>();
|
IntersectionSegmentIds = new List<int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the position
|
||||||
|
/// </summary>
|
||||||
|
[XmlIgnore]
|
||||||
|
public Vector2 Position
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Vector2(X, Y);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
X = value.X;
|
||||||
|
Y = value.Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return string.Format("(node id={0}, {1})", Id, Position);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,11 +44,11 @@ namespace TransportGame.Model.Road
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ParentNetwork.Nodes[Terminal1Id];
|
return (Terminal1Id == -1) ? null : ParentNetwork.Nodes[Terminal1Id];
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Terminal1Id = value.Id;
|
Terminal1Id = (value == null) ? -1 : value.Id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,11 +60,11 @@ namespace TransportGame.Model.Road
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ParentNetwork.Nodes[Terminal2Id];
|
return (Terminal2Id == -1) ? null : ParentNetwork.Nodes[Terminal2Id];
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Terminal2Id = value.Id;
|
Terminal2Id = (value == null) ? -1 : value.Id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +87,13 @@ namespace TransportGame.Model.Road
|
|||||||
{
|
{
|
||||||
LanesTo1 = 1;
|
LanesTo1 = 1;
|
||||||
LanesTo2 = 1;
|
LanesTo2 = 1;
|
||||||
|
Terminal1Id = -1;
|
||||||
|
Terminal2Id = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return string.Format("(segment id={0}, {1}->{2})", Id, Terminal1, Terminal2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Xml.Serialization;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace TransportGame.Model
|
namespace TransportGame.Model
|
||||||
@ -21,12 +22,14 @@ namespace TransportGame.Model
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the X component
|
/// Gets the X component
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float X { get; private set; }
|
[XmlAttribute("x")]
|
||||||
|
public float X { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the Y component
|
/// Gets the Y component
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float Y { get; private set; }
|
[XmlAttribute("y")]
|
||||||
|
public float Y { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a vector2
|
/// Initializes a vector2
|
||||||
|
@ -39,10 +39,10 @@ public class TerrainGeneratorScript : MonoBehaviour
|
|||||||
};
|
};
|
||||||
water.triangles = new[] { 0, 1, 2, 2, 1, 3 };
|
water.triangles = new[] { 0, 1, 2, 2, 1, 3 };
|
||||||
water.uv = new[] {
|
water.uv = new[] {
|
||||||
new Vector2(0, 0),
|
new UnityEngine.Vector2(0, 0),
|
||||||
new Vector2(0, 1),
|
new UnityEngine.Vector2(0, 1),
|
||||||
new Vector2(1, 0),
|
new UnityEngine.Vector2(1, 0),
|
||||||
new Vector2(1, 1)
|
new UnityEngine.Vector2(1, 1)
|
||||||
};
|
};
|
||||||
water.RecalculateNormals();
|
water.RecalculateNormals();
|
||||||
|
|
||||||
@ -102,7 +102,27 @@ public class TerrainGeneratorScript : MonoBehaviour
|
|||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
// Set up textures
|
// Set up textures
|
||||||
SetupSplatmaps(terrainData);
|
//SetupSplatmaps(terrainData);
|
||||||
|
|
||||||
|
// -- DEBUG --
|
||||||
|
|
||||||
|
foreach (var center in map.PopulationCenters)
|
||||||
|
Debug.DrawLine(new Vector3(center.Y, 0, center.X), new Vector3(center.Y, map.Biome.Height, center.X), Color.yellow, 100000);
|
||||||
|
|
||||||
|
// Debug - draw lines
|
||||||
|
if (map != null && map.RoadNetwork != null)
|
||||||
|
{
|
||||||
|
foreach (var segment in map.RoadNetwork.ArticulationSegments)
|
||||||
|
{
|
||||||
|
Color color = (segment.Value.LanesTo1 >= 3) ? Color.magenta : Color.red;
|
||||||
|
Debug.DrawLine(new Vector3(segment.Value.Terminal1.Y, map.Biome.Height / 2, segment.Value.Terminal1.X), new Vector3(segment.Value.Terminal2.Y, map.Biome.Height / 2, segment.Value.Terminal2.X), color, 10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var node in map.RoadNetwork.Nodes)
|
||||||
|
{
|
||||||
|
Debug.DrawLine(new Vector3(node.Value.Y, map.Biome.Height / 2, node.Value.X), new Vector3(node.Value.Y, map.Biome.Height / 2 + 5, node.Value.X), Color.blue, 10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupSplatmaps(TerrainData terrainData)
|
private void SetupSplatmaps(TerrainData terrainData)
|
||||||
@ -162,4 +182,18 @@ public class TerrainGeneratorScript : MonoBehaviour
|
|||||||
void Update()
|
void Update()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnGUI()
|
||||||
|
{
|
||||||
|
Event e = Event.current;
|
||||||
|
if (e.type == EventType.KeyDown)
|
||||||
|
{
|
||||||
|
if (e.keyCode == KeyCode.Home)
|
||||||
|
{
|
||||||
|
Logger.Warning("Writing to file...");
|
||||||
|
Logger.DumpMap(map, "map.map");
|
||||||
|
Logger.Warning("Wrote map to file.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,12 +78,15 @@
|
|||||||
<Compile Include="Assets\Scripts\Generator\TerrainGenerator.cs" />
|
<Compile Include="Assets\Scripts\Generator\TerrainGenerator.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Biome.cs" />
|
<Compile Include="Assets\Scripts\Model\Biome.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Config\TerrainGeneratorConfig.cs" />
|
<Compile Include="Assets\Scripts\Model\Config\TerrainGeneratorConfig.cs" />
|
||||||
|
<Compile Include="Assets\Scripts\Model\IPositionable.cs" />
|
||||||
|
<Compile Include="Assets\Scripts\Model\LineSegment.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Map.cs" />
|
<Compile Include="Assets\Scripts\Model\Map.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Point.cs" />
|
<Compile Include="Assets\Scripts\Model\Rectangle.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Road\RoadNetwork.cs" />
|
<Compile Include="Assets\Scripts\Model\Road\RoadNetwork.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Road\RoadNode.cs" />
|
<Compile Include="Assets\Scripts\Model\Road\RoadNode.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Road\RoadSegment.cs" />
|
<Compile Include="Assets\Scripts\Model\Road\RoadSegment.cs" />
|
||||||
<Compile Include="Assets\Scripts\Model\Texture.cs" />
|
<Compile Include="Assets\Scripts\Model\Texture.cs" />
|
||||||
|
<Compile Include="Assets\Scripts\Model\Vector2.cs" />
|
||||||
<Compile Include="Assets\Scripts\Noise\NoiseGenerator.cs" />
|
<Compile Include="Assets\Scripts\Noise\NoiseGenerator.cs" />
|
||||||
<Compile Include="Assets\Scripts\Noise\PerlinNoiseGenerator.cs" />
|
<Compile Include="Assets\Scripts\Noise\PerlinNoiseGenerator.cs" />
|
||||||
<Compile Include="Assets\Scripts\Unity\InitializeScript.cs" />
|
<Compile Include="Assets\Scripts\Unity\InitializeScript.cs" />
|
||||||
@ -93,6 +96,7 @@
|
|||||||
<Compile Include="Assets\Scripts\Utils\ColorHelper.cs" />
|
<Compile Include="Assets\Scripts\Utils\ColorHelper.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\Expression.cs" />
|
<Compile Include="Assets\Scripts\Utils\Expression.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\Logger.cs" />
|
<Compile Include="Assets\Scripts\Utils\Logger.cs" />
|
||||||
|
<Compile Include="Assets\Scripts\Utils\QuadTree.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\RandomExtensions.cs" />
|
<Compile Include="Assets\Scripts\Utils\RandomExtensions.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\Range.cs" />
|
<Compile Include="Assets\Scripts\Utils\Range.cs" />
|
||||||
<Compile Include="Assets\Scripts\Utils\SerializationHelper.cs" />
|
<Compile Include="Assets\Scripts\Utils\SerializationHelper.cs" />
|
||||||
|
@ -14,20 +14,7 @@ namespace TransportGame.MapViewer.Storage
|
|||||||
{
|
{
|
||||||
public static Map Read(string file)
|
public static Map Read(string file)
|
||||||
{
|
{
|
||||||
Map map = SerializationHelper.DeserializeXml<Map>(file);
|
return SerializationHelper.DeserializeXml<Map>(file);
|
||||||
|
|
||||||
// Fix road network issue
|
|
||||||
foreach (var pair in map.RoadNetwork.ArticulationSegments)
|
|
||||||
pair.Value.ParentNetwork = map.RoadNetwork;
|
|
||||||
|
|
||||||
foreach (var pair in map.RoadNetwork.IntersectionSegments)
|
|
||||||
pair.Value.ParentNetwork = map.RoadNetwork;
|
|
||||||
|
|
||||||
foreach (var pair in map.RoadNetwork.Nodes)
|
|
||||||
pair.Value.ParentNetwork = map.RoadNetwork;
|
|
||||||
|
|
||||||
// Done
|
|
||||||
return map;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user