Merged branch master into new-netcode

This commit is contained in:
juanjp600
2016-09-27 19:45:14 -03:00
20 changed files with 712 additions and 253 deletions

View File

@@ -137,6 +137,7 @@
<Compile Include="Source\Map\EntityGrid.cs" />
<Compile Include="Source\Map\FireSource.cs" />
<Compile Include="Source\Map\Levels\CaveGenerator.cs" />
<Compile Include="Source\Map\Levels\LevelGenerationParams.cs" />
<Compile Include="Source\Map\Levels\LevelRenderer.cs" />
<Compile Include="Source\Map\Levels\Ruins\BTRoom.cs" />
<Compile Include="Source\Map\Levels\Ruins\Corridor.cs" />
@@ -347,6 +348,15 @@
<Content Include="Content\BackgroundSprites\vegetation2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\BackgroundSprites\vegetation3.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\BackgroundSprites\vegetation4.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\BackgroundSprites\vegetation5.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\Characters\Charybdis\charybdis.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -767,6 +777,10 @@
<Content Include="Content\Map\iceWall.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\Map\LevelGenerationParameters.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<SubType>Designer</SubType>
</Content>
<Content Include="Content\Map\locationNames.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

View File

@@ -1,34 +1,86 @@
<?xml version="1.0" encoding="utf-8" ?>
<backgroundsprites>
<hanging1 alignment="Bottom" minsize="0.5" maxsize="1.5" commonness="5">
<Sprite texture="Content/BackgroundSprites/vegetation.png" sourcerect="0,0,242,543" origin="0.5,0.0"/>
<Sprite texture="Content/BackgroundSprites/vegetation.png" sourcerect="0,0,242,543" origin="0.5,0.15"/>
</hanging1>
<hanging2 alignment="Bottom" minsize="0.5" maxsize="1.5" commonness="5">
<Sprite texture="Content/BackgroundSprites/vegetation.png" sourcerect="241,0,322,720" origin="0.5,0.0"/>
<Sprite texture="Content/BackgroundSprites/vegetation.png" sourcerect="241,0,322,720" origin="0.5,0.15"/>
</hanging2>
<kelp1 alignment="Top" minsize="0.5" maxsize="1.5" commonness="10">
<overridecommonness commonness="0" leveltype="Open" />
<Sprite texture="Content/BackgroundSprites/vegetation.png" sourcerect="0,667,275,357" origin="0.5,1.0"/>
</kelp1>
<stalk alignment="Top" minsize="0.5" maxsize="1.5" commonness="1" randomrotation="-10,10">
<stalk alignment="Top" minsize="0.5" maxsize="1.5" commonness="1" swingamount="2" randomrotation="-10,10">
<overridecommonness commonness="0" leveltype="Open" />
<overridecommonness commonness="5" leveltype="Maze" />
<Sprite texture="Content/BackgroundSprites/vegetation.png" sourcerect="775,0,249,849" origin="0.5,0.95"/>
</stalk>
<spike alignment="Top" minsize="0.5" maxsize="1.5" alignwithsurface="true" randomrotation="-20,20" commonness="2">
<overridecommonness commonness="0" leveltype="Open" />
<Sprite texture="Content/BackgroundSprites/vegetation.png" sourcerect="544,0,228,561" origin="0.5,0.95"/>
</spike>
<branches1 minsize="0.5" maxsize="2.0" alignwithsurface="true" randomrotation="-20,20" commonness="4">
<leaves minsize="0.5" maxsize="1.5" alignwithsurface="true" commonness="3">
<Sprite texture="Content/BackgroundSprites/vegetation.png" sourcerect="305,722,461,301" origin="0.6,0.8"/>
</leaves>
<branches1 minsize="0.5" maxsize="2.0" alignwithsurface="true" swingamount="3" randomrotation="-20,20" commonness="4">
<overridecommonness commonness="10" leveltype="Maze" />
<Sprite texture="Content/BackgroundSprites/vegetation2.png" sourcerect="0,0,525,484" origin="0.5,0.9"/>
</branches1>
<branches2 minsize="0.5" maxsize="2.0" alignwithsurface="true" randomrotation="-20,20" commonness="4">
<Sprite texture="Content/BackgroundSprites/vegetation2.png" sourcerect="255,0,246,479" origin="0.5,0.9"/>
<branches2 minsize="0.5" maxsize="2.0" alignwithsurface="true" swingamount="3" randomrotation="-20,20" commonness="4">
<overridecommonness commonness="10" leveltype="Maze" />
<Sprite texture="Content/BackgroundSprites/vegetation2.png" sourcerect="247,0,278,479" origin="0.2,0.9"/>
</branches2>
<fungus minsize="0.5" maxsize="1.5" alignwithsurface="true" commonness="3">
<branches3 minsize="0.5" maxsize="2.0" alignwithsurface="true" swingamount="3" randomrotation="-20,20" commonness="4">
<overridecommonness commonness="10" leveltype="Maze" />
<Sprite texture="Content/BackgroundSprites/vegetation2.png" sourcerect="526,0,245,479" origin="0.4,0.9"/>
</branches3>
<fungus minsize="0.5" maxsize="1.5" alignwithsurface="true" swingamount="1" commonness="3">
<overridecommonness commonness="10" leveltype="Maze" />
<Sprite texture="Content/BackgroundSprites/vegetation2.png" sourcerect="0,681,442,343" origin="0.5,0.9"/>
</fungus>
<thistle alignment="Top" minsize="0.5" maxsize="1.5" randomrotation="-10,10" swingamount="5" commonness="3">
<overridecommonness commonness="0" leveltype="Open" />
<Sprite texture="Content/BackgroundSprites/vegetation2.png" sourcerect="449,500,252,524" origin="0.5,0.95"/>
</thistle>
<branch alignment="Top" minsize="1" maxsize="3" randomrotation="-30,30" swingamount="10" commonness="10">
<overridecommonness commonness="0" leveltype="Open" />
<overridecommonness commonness="1" leveltype="Pillars" />
<overridecommonness commonness="1" leveltype="Slabs" />
<Sprite texture="Content/BackgroundSprites/vegetation3.png" origin="0.5,0.95"/>
</branch>
<branch alignment="Top" minsize="1" maxsize="3" randomrotation="-30,30" swingamount="8" commonness="10">
<overridecommonness commonness="0" leveltype="Open" />
<overridecommonness commonness="1" leveltype="Pillars" />
<overridecommonness commonness="1" leveltype="Slabs" />
<Sprite texture="Content/BackgroundSprites/vegetation4.png" sourcerect="0,0,818,1024" origin="0.5,0.95"/>
</branch>
<hay alignment="Top" minsize="0.5" maxsize="1.5" randomrotation="-10,10" swingamount="5" commonness="3">
<overridecommonness commonness="0" leveltype="Open" />
<Sprite texture="Content/BackgroundSprites/vegetation4.png" sourcerect="820,245,204,779" origin="0.5,0.95"/>
</hay>
<branch minsize="1" maxsize="3" alignwithsurface="true" randomrotation="-30,30" swingamount="10" commonness="0">
<overridecommonness commonness="10" leveltype="Pillars" />
<overridecommonness commonness="10" leveltype="Slabs" />
<Sprite texture="Content/BackgroundSprites/vegetation5.png" sourcerect="0,0,555,1024" origin="0.6,0.95"/>
</branch>
<branch minsize="1" maxsize="3" alignwithsurface="true" randomrotation="-30,30" swingamount="10" commonness="0">
<overridecommonness commonness="10" leveltype="Pillars" />
<overridecommonness commonness="10" leveltype="Slabs" />
<Sprite texture="Content/BackgroundSprites/vegetation5.png" sourcerect="580,151,444,873" origin="0.3,0.95"/>
</branch>
</backgroundsprites>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 984 KiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 832 KiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 KiB

View File

@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8" ?>
<LevelGenerationParameters>
<Default
width="150000"
height="60000"
VoronoiSiteInterval="2000,2000"
VoronoiSiteVariance="800,800"
MainPathNodeIntervalRange="10000,30000"
BackgroundColor="29,36,50"
SmallTunnelCount="5"
SmallTunnelLengthRange="5000,10000"
RuinCount="1"
BottomHoleProbability="0.4"
BackgroundSpriteAmount="1000"
/>
<Open
width="200000"
height="50000"
VoronoiSiteInterval="2000,2000"
VoronoiSiteVariance="800,800"
MainPathNodeIntervalRange="5000,10000"
BackgroundColor="55,61,72"
SmallTunnelCount="3"
SmallTunnelLengthRange="5000,10000"
RuinCount="1"
BottomHoleProbability="1"
BackgroundSpriteAmount="800"
/>
<Pillars
width="100000"
height="80000"
VoronoiSiteInterval="1000,8000"
VoronoiSiteVariance="100,1400"
MainPathNodeIntervalRange="5000,10000"
BackgroundColor="55,72,58"
SmallTunnelCount="10"
SmallTunnelLengthRange="5000,10000"
RuinCount="1"
BottomHoleProbability="0.5"
BackgroundSpriteAmount="1000"
/>
<Slabs
width="150000"
height="50000"
VoronoiSiteInterval="8000,1000"
VoronoiSiteVariance="1400,100"
MainPathNodeIntervalRange="5000,10000"
BackgroundColor="55,72,58"
SmallTunnelCount="10"
SmallTunnelLengthRange="5000,10000"
RuinCount="1"
BottomHoleProbability="0.0"
BackgroundSpriteAmount="1000"
/>
<Maze
width="100000"
height="70000"
VoronoiSiteInterval="1500,1500"
VoronoiSiteVariance="700,700"
MainPathNodeIntervalRange="6000,10000"
BackgroundColor="25,23,10"
SmallTunnelCount="10"
SmallTunnelLengthRange="5000,50000"
RuinCount="3"
BottomHoleProbability="0.5"
BackgroundSpriteAmount="1000"
/>
</LevelGenerationParameters>

View File

@@ -35,10 +35,11 @@ namespace Barotrauma
const int GridSize = 1000;
private List<BackgroundSpritePrefab> prefabs = new List<BackgroundSpritePrefab>();
private List<BackgroundSprite>[,] sprites;
private float swingTimer;
public BackgroundSpriteManager(string configPath)
{
LoadConfig(configPath);
@@ -83,38 +84,37 @@ namespace Barotrauma
for (int i = 0 ; i < amount; i++)
{
BackgroundSpritePrefab prefab = GetRandomPrefab();
BackgroundSpritePrefab prefab = GetRandomPrefab(level.GenerationParams.Name);
GraphEdge selectedEdge = null;
Vector2? pos = FindSpritePosition(level, prefab, out selectedEdge);
Vector2 edgeNormal = Vector2.One;
Vector2? pos = FindSpritePosition(level, prefab, out selectedEdge, out edgeNormal);
if (pos == null) continue;
float rotation = 0.0f;
if (prefab.AlignWithSurface)
{
Vector2 leftPoint = selectedEdge.point2;
Vector2 rightPoint = selectedEdge.point1;
rotation = -MathUtils.VectorToAngle(rightPoint - leftPoint);
rotation = MathUtils.VectorToAngle(new Vector2(edgeNormal.Y, edgeNormal.X));
}
rotation += Rand.Range(prefab.RandomRotation.X, prefab.RandomRotation.Y, false);
var newSprite = new BackgroundSprite(prefab,
(Vector2)pos, Rand.Range(prefab.Scale.X, prefab.Scale.Y, false), rotation);
int x = (int)Math.Floor(((Vector2)pos).X / GridSize);
if (x<0 || x >= sprites.GetLength(0)) continue;
if (x < 0 || x >= sprites.GetLength(0)) continue;
int y = (int)Math.Floor(((Vector2)pos).Y / GridSize);
if (y<0 || y >= sprites.GetLength(1)) continue;
if (y < 0 || y >= sprites.GetLength(1)) continue;
sprites[x,y].Add(newSprite);
}
}
private Vector2? FindSpritePosition(Level level, BackgroundSpritePrefab prefab, out GraphEdge closestEdge)
private Vector2? FindSpritePosition(Level level, BackgroundSpritePrefab prefab, out GraphEdge closestEdge, out Vector2 edgeNormal)
{
closestEdge = null;
edgeNormal = Vector2.One;
Vector2 randomPos = new Vector2(
Rand.Range(0.0f, level.Size.X, false),
@@ -126,68 +126,67 @@ namespace Barotrauma
VoronoiCell cell = cells[Rand.Int(cells.Count, false)];
List<GraphEdge> edges = new List<GraphEdge>();
List<Vector2> normals = new List<Vector2>();
foreach (GraphEdge edge in cell.edges)
{
if (!edge.isSolid) continue;
if (!edge.isSolid || edge.OutsideLevel) continue;
Vector2 normal = edge.GetNormal(cell);
if (prefab.Alignment.HasFlag(Alignment.Bottom))
{
if (Math.Abs(edge.point1.X - edge.point2.X) < Math.Abs(edge.point1.Y - edge.point2.Y)) continue;
if (edge.Center.Y < cell.Center.Y) edges.Add(edge);
}
else if (prefab.Alignment.HasFlag(Alignment.Top))
{
if (Math.Abs(edge.point1.X - edge.point2.X) < Math.Abs(edge.point1.Y - edge.point2.Y)) continue;
if (edge.Center.Y > cell.Center.Y) edges.Add(edge);
}
else if (prefab.Alignment.HasFlag(Alignment.Left))
{
if (edge.Center.X < cell.Center.X) edges.Add(edge);
}
else if (prefab.Alignment.HasFlag(Alignment.Right))
{
if (edge.Center.X > cell.Center.X) edges.Add(edge);
}
else
if (prefab.Alignment.HasFlag(Alignment.Bottom) && normal.Y < -0.5f)
{
edges.Add(edge);
}
else if (prefab.Alignment.HasFlag(Alignment.Top) && normal.Y > 0.5f)
{
edges.Add(edge);
}
else if (prefab.Alignment.HasFlag(Alignment.Left) && normal.X < -0.5f)
{
edges.Add(edge);
}
else if (prefab.Alignment.HasFlag(Alignment.Right) && normal.X > 0.5f)
{
edges.Add(edge);
}
else
{
continue;
}
normals.Add(normal);
}
if (!edges.Any()) return null;
closestEdge = edges[Rand.Int(edges.Count,false)];
int index = Rand.Int(edges.Count,false);
closestEdge = edges[index];
edgeNormal = normals[index];
float length = Vector2.Distance(closestEdge.point1, closestEdge.point2);
Vector2 dir = (closestEdge.point1 - closestEdge.point2) / length;
Vector2 pos = closestEdge.Center;
pos = closestEdge.point2 + dir * Rand.Range(prefab.Sprite.size.X / 2.0f, length - prefab.Sprite.size.X / 2.0f, false);
if (prefab.Alignment.HasFlag(Alignment.Top))
{
pos.Y -= Math.Abs(dir.Y) * prefab.Sprite.size.X / Math.Abs(dir.X);
}
else if (prefab.Alignment.HasFlag(Alignment.Bottom))
{
pos.Y += Math.Abs(dir.Y) * prefab.Sprite.size.X / Math.Abs(dir.X);
}
Vector2 pos = closestEdge.point2 + dir * Rand.Range(prefab.Sprite.size.X / 2.0f, length - prefab.Sprite.size.X / 2.0f, false);
return pos;
}
public void Update(float deltaTime)
{
swingTimer += deltaTime;
}
public void DrawSprites(SpriteBatch spriteBatch, Camera cam)
{
Rectangle indices = Rectangle.Empty;
indices.X = (int)Math.Floor(cam.WorldView.X / (float)GridSize) - 1;
indices.X = (int)Math.Floor(cam.WorldView.X / (float)GridSize) - 2;
if (indices.X >= sprites.GetLength(0)) return;
indices.Y = (int)Math.Floor((cam.WorldView.Y - cam.WorldView.Height) / (float)GridSize) - 1;
indices.Y = (int)Math.Floor((cam.WorldView.Y - cam.WorldView.Height) / (float)GridSize) - 2;
if (indices.Y >= sprites.GetLength(1)) return;
indices.Width = (int)Math.Ceiling(cam.WorldView.Right / (float)GridSize) + 1;
indices.Width = (int)Math.Ceiling(cam.WorldView.Right / (float)GridSize) + 2;
if (indices.Width < 0) return;
indices.Height = (int)Math.Ceiling(cam.WorldView.Y / (float)GridSize) + 1;
indices.Height = (int)Math.Ceiling(cam.WorldView.Y / (float)GridSize) + 2;
if (indices.Height < 0) return;
indices.X = Math.Max(indices.X, 0);
@@ -195,6 +194,8 @@ namespace Barotrauma
indices.Width = Math.Min(indices.Width, sprites.GetLength(0));
indices.Height = Math.Min(indices.Height, sprites.GetLength(1));
float swingState = (float)Math.Sin(swingTimer * 0.1f);
float z = 0.0f;
for (int x = indices.X; x < indices.Width; x++)
{
@@ -202,31 +203,44 @@ namespace Barotrauma
{
foreach (BackgroundSprite sprite in sprites[x, y])
{
sprite.Prefab.Sprite.Draw(spriteBatch, new Vector2(sprite.Position.X, -sprite.Position.Y), Color.White, sprite.Rotation, sprite.Scale, SpriteEffects.None, z);
sprite.Prefab.Sprite.Draw(
spriteBatch,
new Vector2(sprite.Position.X, -sprite.Position.Y),
Color.White,
sprite.Rotation + swingState*sprite.Prefab.SwingAmount,
sprite.Scale,
SpriteEffects.None,
z);
if (GameMain.DebugDraw)
{
GUI.DrawRectangle(spriteBatch, new Vector2(sprite.Position.X, -sprite.Position.Y), new Vector2(10.0f, 10.0f), Color.Red, true);
}
z += 0.0001f;
}
}
}
}
private BackgroundSpritePrefab GetRandomPrefab()
private BackgroundSpritePrefab GetRandomPrefab(string levelType)
{
int totalCommonness = 0;
foreach (BackgroundSpritePrefab prefab in prefabs)
{
totalCommonness += prefab.Commonness;
totalCommonness += prefab.GetCommonness(levelType);
}
float randomNumber = Rand.Int(totalCommonness+1, false);
foreach (BackgroundSpritePrefab prefab in prefabs)
{
if (randomNumber <= prefab.Commonness)
if (randomNumber <= prefab.GetCommonness(levelType))
{
return prefab;
}
randomNumber -= prefab.Commonness;
randomNumber -= prefab.GetCommonness(levelType);
}
return null;

View File

@@ -1,5 +1,6 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Xml.Linq;
namespace Barotrauma
@@ -16,13 +17,20 @@ namespace Barotrauma
public readonly Vector2 RandomRotation;
public readonly float SwingAmount;
public readonly int Commonness;
public Dictionary<string, int> OverrideCommonness;
public BackgroundSpritePrefab(XElement element)
{
string alignmentStr = ToolBox.GetAttributeString(element, "alignment", "BottomCenter");
string alignmentStr = ToolBox.GetAttributeString(element, "alignment", "");
if (!Enum.TryParse(alignmentStr, out Alignment)) Alignment = Alignment.BottomCenter;
if (string.IsNullOrEmpty(alignmentStr) || !Enum.TryParse(alignmentStr, out Alignment))
{
Alignment = Alignment.Top | Alignment.Bottom | Alignment.Left | Alignment.Right;
}
Commonness = ToolBox.GetAttributeInt(element, "commonness", 1);
@@ -35,14 +43,39 @@ namespace Barotrauma
RandomRotation.X = MathHelper.ToRadians(RandomRotation.X);
RandomRotation.Y = MathHelper.ToRadians(RandomRotation.Y);
SwingAmount = MathHelper.ToRadians(ToolBox.GetAttributeFloat(element, "swingamount", 0.0f));
OverrideCommonness = new Dictionary<string, int>();
foreach (XElement subElement in element.Elements())
{
if (subElement.Name.ToString().ToLowerInvariant() != "sprite") continue;
switch(subElement.Name.ToString().ToLowerInvariant())
{
case "sprite":
Sprite = new Sprite(subElement);
break;
case "overridecommonness":
string levelType = ToolBox.GetAttributeString(subElement, "leveltype", "");
if (!OverrideCommonness.ContainsKey(levelType))
{
OverrideCommonness.Add(levelType, ToolBox.GetAttributeInt(subElement, "commonness", 1));
}
break;
Sprite = new Sprite(subElement);
break;
}
}
}
public int GetCommonness(string levelType)
{
int commonness = 0;
if (!OverrideCommonness.TryGetValue(levelType, out commonness))
{
return Commonness;
}
return commonness;
}
}
}

View File

@@ -10,7 +10,17 @@ namespace Barotrauma
{
public enum ContentType
{
None, Jobs, Item, Character, Structure, Executable, LocationTypes, RandomEvents, Missions, BackgroundCreaturePrefabs, BackgroundSpritePrefabs
None,
Jobs,
Item,
Character,
Structure,
Executable,
LocationTypes,
LevelGenerationPresets,
RandomEvents,
Missions,
BackgroundCreaturePrefabs, BackgroundSpritePrefabs
}
public class ContentPackage

View File

@@ -495,10 +495,6 @@ namespace Barotrauma
case "fire":
if (GameMain.Client == null) Hull.EditFire = !Hull.EditFire;
break;
case "generatelevel":
GameMain.Level = new Level("asdf", 50.0f, 500,500, 50);
GameMain.Level.Generate();
break;
case "fixitems":
foreach (Item it in Item.ItemList)

View File

@@ -218,6 +218,7 @@ namespace Barotrauma
Mission.Init();
MapEntityPrefab.Init();
LevelGenerationParams.LoadPresets();
TitleScreen.LoadState = 10.0f;
yield return CoroutineStatus.Running;

View File

@@ -189,16 +189,18 @@ namespace Barotrauma
{
Site site = (i == 0) ? ge.site1 : ge.site2;
VoronoiCell cell = cellGrid[
(int)Math.Floor((site.coord.x-borders.X) / gridCellSize),
(int)Math.Floor((site.coord.y-borders.Y) / gridCellSize)].Find(c => c.site == site);
int x = (int)(Math.Floor((site.coord.x-borders.X) / gridCellSize));
int y = (int)(Math.Floor((site.coord.y-borders.Y) / gridCellSize));
x = MathHelper.Clamp(x, 0, cellGrid.GetLength(0)-1);
y = MathHelper.Clamp(y, 0, cellGrid.GetLength(1)-1);
VoronoiCell cell = cellGrid[x,y].Find(c => c.site == site);
if (cell == null)
{
cell = new VoronoiCell(site);
cellGrid[
(int)Math.Floor((cell.Center.X-borders.X) / gridCellSize),
(int)Math.Floor((cell.Center.Y - borders.Y) / gridCellSize)].Add(cell);
cellGrid[x, y].Add(cell);
cells.Add(cell);
}

View File

@@ -50,9 +50,7 @@ namespace Barotrauma
public const float ExitDistance = 6000.0f;
private string seed;
private int siteInterval;
public const int GridCellSize = 2000;
private List<VoronoiCell>[,] cellGrid;
@@ -77,6 +75,8 @@ namespace Barotrauma
private Color backgroundColor;
private LevelGenerationParams generationParams;
public Vector2 StartPosition
{
get { return startPosition; }
@@ -119,29 +119,32 @@ namespace Barotrauma
private set;
}
public LevelGenerationParams GenerationParams
{
get { return generationParams; }
}
public Color BackgroundColor
{
get { return backgroundColor; }
}
public Level(string seed, float difficulty, int width, int height, int siteInterval)
public Level(string seed, float difficulty, LevelGenerationParams generationParams)
{
this.seed = seed;
this.siteInterval = siteInterval;
this.Difficulty = difficulty;
borders = new Rectangle(0, 0, width, height);
this.generationParams = generationParams;
borders = new Rectangle(0, 0, (int)generationParams.Width, (int)generationParams.Height);
}
public static Level CreateRandom(LocationConnection locationConnection)
{
string seed = locationConnection.Locations[0].Name + locationConnection.Locations[1].Name;
Rand.SetSyncedSeed(ToolBox.StringToInt(seed));
return new Level(seed, locationConnection.Difficulty, Rand.Range(80000, 120000, false), Rand.Range(40000, 60000, false), 2000);
return new Level(seed, locationConnection.Difficulty, LevelGenerationParams.GetRandom(seed));
}
public static Level CreateRandom(string seed = "")
@@ -153,10 +156,10 @@ namespace Barotrauma
Rand.SetSyncedSeed(ToolBox.StringToInt(seed));
return new Level(seed, Rand.Range(30.0f, 80.0f, false), Rand.Range(80000, 120000, false), Rand.Range(40000, 60000, false), 2000);
return new Level(seed, Rand.Range(30.0f, 80.0f, false), LevelGenerationParams.GetRandom(seed));
}
public void Generate(bool mirror=false)
public void Generate(bool mirror = false)
{
Stopwatch sw = new Stopwatch();
sw.Start();
@@ -175,47 +178,50 @@ namespace Barotrauma
bodies = new List<Body>();
Rand.SetSyncedSeed(ToolBox.StringToInt(seed));
float brightness = Rand.Range(1.0f, 1.3f, false);
backgroundColor = Color.Lerp(new Color(11, 18, 26), new Color(50, 46, 20), Rand.Range(0.0f, 1.0f, false)) * brightness;
backgroundColor = new Color(backgroundColor, 1.0f);
backgroundColor = generationParams.BackgroundColor;
float avgValue = (backgroundColor.R + backgroundColor.G + backgroundColor.G) / 3;
GameMain.LightManager.AmbientLight = new Color(backgroundColor * (60.0f / avgValue), 1.0f);
float minWidth = Submarine.MainSub == null ? 0.0f : Math.Max(Submarine.MainSub.Borders.Width, Submarine.MainSub.Borders.Height);
minWidth = Math.Max(minWidth, 6500.0f);
startPosition = new Vector2(minWidth * 2, Rand.Range(minWidth * 2, borders.Height - minWidth * 2, false));
endPosition = new Vector2(borders.Width - minWidth * 2, Rand.Range(minWidth * 2, borders.Height - minWidth * 2, false));
startPosition = new Vector2(
Rand.Range(minWidth * 2, minWidth * 4, false),
Rand.Range(borders.Height * 0.5f, borders.Height - minWidth * 2, false));
endPosition = new Vector2(
borders.Width - Rand.Range(minWidth * 2, minWidth * 4, false),
Rand.Range(borders.Height * 0.5f, borders.Height - minWidth * 2, false));
List<Vector2> pathNodes = new List<Vector2>();
Rectangle pathBorders = borders;// new Rectangle((int)minWidth, (int)minWidth, borders.Width - (int)minWidth * 2, borders.Height - (int)minWidth);
pathBorders.Inflate(-minWidth*2, -minWidth*2);
pathNodes.Add(new Vector2(startPosition.X, borders.Height));
pathNodes.Add(startPosition);
Vector2 nodeInterval = generationParams.MainPathNodeIntervalRange;
for (float x = startPosition.X; x < endPosition.X; x += Rand.Range(5000.0f, 10000.0f, false))
for (float x = startPosition.X + Rand.Range(nodeInterval.X, nodeInterval.Y, false);
x < endPosition.X - Rand.Range(nodeInterval.X, nodeInterval.Y, false);
x += Rand.Range(nodeInterval.X, nodeInterval.Y, false))
{
pathNodes.Add(new Vector2(x, Rand.Range(pathBorders.Y, pathBorders.Bottom, false)));
}
pathNodes.Add(endPosition);
pathNodes.Add(new Vector2(endPosition.X, borders.Height));
int smallTunnelCount = 5;
List<List<Vector2>> smallTunnels = new List<List<Vector2>>();
for (int i = 0; i < smallTunnelCount; i++)
for (int i = 0; i < generationParams.SmallTunnelCount; i++)
{
var tunnelStartPos = pathNodes[Rand.Range(2, pathNodes.Count - 2, false)];
tunnelStartPos.X = MathHelper.Clamp(tunnelStartPos.X, pathBorders.X, pathBorders.Right);
float tunnelLength = Rand.Range(5000.0f, 10000.0f, false);
float tunnelLength = Rand.Range(
generationParams.SmallTunnelLengthRange.X,
generationParams.SmallTunnelLengthRange.Y,
false);
var tunnelNodes = MathUtils.GenerateJaggedLine(
tunnelStartPos,
@@ -231,21 +237,23 @@ namespace Barotrauma
if (tunnel.Any()) smallTunnels.Add(tunnel);
}
float siteVariance = siteInterval * 0.4f;
for (int x = siteInterval / 2; x < borders.Width; x += siteInterval)
Vector2 siteInterval = generationParams.VoronoiSiteInterval;
Vector2 siteVariance = generationParams.VoronoiSiteVariance;
for (float x = siteInterval.X / 2; x < borders.Width; x += siteInterval.X)
{
for (int y = siteInterval / 2; y < borders.Height; y += siteInterval)
for (float y = siteInterval.Y / 2; y < borders.Height; y += siteInterval.Y)
{
Vector2 site = new Vector2(x, y) + Rand.Vector(siteVariance, false);
Vector2 site = new Vector2(
x + Rand.Range(-siteVariance.X, siteVariance.X, false),
y + Rand.Range(-siteVariance.Y, siteVariance.Y, false));
if (smallTunnels.Any(t => t.Any(node => Vector2.Distance(node, site) < siteInterval)))
if (smallTunnels.Any(t => t.Any(node => Vector2.Distance(node, site) < siteInterval.Length())))
{
if (x < borders.Width - siteInterval) sites.Add(new Vector2(x, y) + Vector2.UnitX * siteInterval * 0.5f);
if (y < borders.Height - siteInterval) sites.Add(new Vector2(x, y) + Vector2.UnitY * siteInterval * 0.5f);
if (x < borders.Width - siteInterval && y < borders.Height - siteInterval) sites.Add(new Vector2(x, y) + Vector2.One * siteInterval * 0.5f);
//add some more sites around the small tunnels to generate more small voronoi cells
if (x < borders.Width - siteInterval.X) sites.Add(new Vector2(x, y) + Vector2.UnitX * siteInterval * 0.5f);
if (y < borders.Height - siteInterval.Y) sites.Add(new Vector2(x, y) + Vector2.UnitY * siteInterval * 0.5f);
if (x < borders.Width - siteInterval.X && y < borders.Height - siteInterval.Y) sites.Add(new Vector2(x, y) + Vector2.One * siteInterval * 0.5f);
}
if (mirror) site.X = borders.Width - site.X;
@@ -259,7 +267,6 @@ namespace Barotrauma
List<GraphEdge> graphEdges = voronoi.MakeVoronoiGraph(sites, borders.Width, borders.Height);
Debug.WriteLine("MakeVoronoiGraph: " + sw2.ElapsedMilliseconds + " ms");
sw2.Restart();
@@ -270,8 +277,7 @@ namespace Barotrauma
sw2.Restart();
List<VoronoiCell> mainPath = CaveGenerator.GeneratePath(pathNodes, cells, cellGrid, GridCellSize,
new Rectangle(pathBorders.X, pathBorders.Y, pathBorders.Width, borders.Height), 0.3f, mirror);
new Rectangle(pathBorders.X, pathBorders.Y, pathBorders.Width, borders.Height), 0.5f, mirror);
for (int i = 2; i < mainPath.Count; i += 3)
{
@@ -315,12 +321,20 @@ namespace Barotrauma
cells = CleanCells(pathCells);
pathCells.AddRange(CreateBottomHoles(Rand.Range(0.1f,0.8f, false), new Rectangle(
pathCells.AddRange(CreateBottomHoles(generationParams.BottomHoleProbability, new Rectangle(
(int)(borders.Width * 0.2f), 0,
(int)(borders.Width * 0.6f), (int)(borders.Height * 0.3f))));
(int)(borders.Width * 0.6f), (int)(borders.Height * 0.8f))));
foreach (VoronoiCell cell in cells)
{
if (cell.Center.Y < borders.Height / 2) continue;
cell.edges.ForEach(e => e.OutsideLevel = true);
}
foreach (VoronoiCell cell in pathCells)
{
cell.edges.ForEach(e => e.OutsideLevel = false);
cell.CellType = CellType.Path;
cells.Remove(cell);
}
@@ -408,92 +422,33 @@ namespace Barotrauma
cellGrid[x, y].Add(cell);
}
Vector2 ruinSize = new Vector2(Rand.Range(5000.0f, 8000.0f, false), Rand.Range(5000.0f, 8000.0f, false));
float ruinRadius = Math.Max(ruinSize.X, ruinSize.Y) * 0.5f;
Vector2 ruinPos = cells[Rand.Int(cells.Count, false)].Center;
int iter = 0;
while (mainPath.Any(p => Vector2.Distance(ruinPos, p.Center) < ruinRadius*2.0f))
for (int i = 0; i<generationParams.RuinCount; i++)
{
Vector2 weighedPathPos = ruinPos;
iter++;
foreach (VoronoiCell pathCell in mainPath)
{
float dist = Vector2.Distance(pathCell.Center, ruinPos);
if (dist > 10000.0f) continue;
Vector2 moveAmount = Vector2.Normalize(ruinPos - pathCell.Center) * 100000.0f / dist;
//if (weighedPathPos.Y + moveAmount.Y > borders.Bottom - ruinSize.X)
//{
// moveAmount.X = (Math.Abs(moveAmount.Y) + Math.Abs(moveAmount.X))*Math.Sign(moveAmount.X);
// moveAmount.Y = 0.0f;
//}
weighedPathPos += moveAmount;
}
ruinPos = weighedPathPos;
if (iter > 10000) break;
}
VoronoiCell closestPathCell = null;
float closestDist = 0.0f;
foreach (VoronoiCell pathCell in mainPath)
{
float dist = Vector2.Distance(pathCell.Center, ruinPos);
if (closestPathCell == null || dist < closestDist)
{
closestPathCell = pathCell;
closestDist = dist;
}
}
var ruin = new Ruin(closestPathCell, cells, new Rectangle((ruinPos - ruinSize * 0.5f).ToPoint(), ruinSize.ToPoint()));
ruins = new List<Ruin>();
ruins.Add(ruin);
ruin.RuinShapes.Sort((shape1, shape2) => shape2.DistanceFromEntrance.CompareTo(shape1.DistanceFromEntrance));
for (int i = 0; i < 4; i++ )
{
positionsOfInterest.Add(new InterestingPosition(ruin.RuinShapes[i].Rect.Center.ToVector2(), PositionType.Ruin));
GenerateRuin(mainPath);
}
startPosition.Y = borders.Height;
endPosition.Y = borders.Height;
List<VoronoiCell> cellsWithBody = new List<VoronoiCell>(cells);
foreach (RuinShape ruinShape in ruin.RuinShapes)
{
var tooClose = GetTooCloseCells(ruinShape.Rect.Center.ToVector2(), Math.Max(ruinShape.Rect.Width, ruinShape.Rect.Height));
tooClose.ForEach(c =>
{
if (c.edges.Any(e => ruinShape.Rect.Contains(e.point1) || ruinShape.Rect.Contains(e.point2))) c.CellType = CellType.Empty;
});
}
List<VertexPositionColor> bodyVertices;
bodies = CaveGenerator.GeneratePolygons(cellsWithBody, out bodyVertices);
renderer.SetBodyVertices(bodyVertices.ToArray());
renderer.SetWallVertices(CaveGenerator.GenerateWallShapes(cells));
renderer.PlaceSprites(1000);
renderer.PlaceSprites(generationParams.BackgroundSpriteAmount);
wrappingWalls = new WrappingWall[2, 2];
Rectangle ignoredArea = new Rectangle((int)startPosition.X, 0, (int)(endPosition.X - startPosition.X), borders.Height);
for (int side = 0; side < 2; side++)
{
for (int i = 0; i < 2; i++)
{
wrappingWalls[side, i] = new WrappingWall(pathCells, cells, borders.Height * 0.5f,
wrappingWalls[side, i] = new WrappingWall(pathCells, cells, ignoredArea,
(side == 0 ? -1 : 1) * (i + 1));
List<VertexPositionColor> wrappingWallVertices;
@@ -532,27 +487,18 @@ namespace Barotrauma
edge.site1 = null;
edge.site2 = null;
}
}
Debug.WriteLine("Generatelevel: " + sw2.ElapsedMilliseconds + " ms");
sw2.Restart();
//vertexBuffer = new VertexBuffer(GameMain.CurrGraphicsDevice, VertexPositionTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
//vertexBuffer.SetData(vertices);
if (mirror)
{
Vector2 temp = startPosition;
startPosition = endPosition;
endPosition = temp;
}
//RuinGeneration.RuinGenerator.Draw(spriteBatch);
Debug.WriteLine("**********************************************************************************");
Debug.WriteLine("Generated a map with " + sites.Count + " sites in " + sw.ElapsedMilliseconds + " ms");
Debug.WriteLine("Seed: "+seed);
@@ -569,15 +515,26 @@ namespace Barotrauma
if (!limits.Contains(cell.Center)) continue;
float closestDist = 0.0f;
WayPoint closestWayPoint = null;
foreach (WayPoint wp in WayPoint.WayPointList)
{
if (wp.SpawnType != SpawnType.Path) continue;
float dist =Math.Abs(cell.Center.X - wp.WorldPosition.X);
if (closestWayPoint == null || dist < closestDist)
{
closestDist = dist;
closestWayPoint = wp;
}
}
if (closestWayPoint.WorldPosition.Y < cell.Center.Y) continue;
toBeRemoved.Add(cell);
}
return toBeRemoved;
//foreach (VoronoiCell cell in toBeRemoved)
//{
// cells.Remove(cell);
//}
}
private void EnlargeMainPath(List<VoronoiCell> pathCells, float minWidth)
@@ -692,22 +649,7 @@ namespace Barotrauma
if (tooClose && !tooCloseCells.Contains(cell)) tooCloseCells.Add(cell);
}
//for (float x = -minDistance; x <= minDistance; x+=siteInterval)
//{
// for (float y = -minDistance; y <= minDistance; y += siteInterval)
// {
// Vector2 cornerPos = position + new Vector2(x,y);
// int cellIndex = CaveGenerator.FindCellIndex(cornerPos, cells, cellGrid, GridCellSize);
// if (cellIndex == -1) continue;
// if (!tooCloseCells.Contains(cells[cellIndex]))
// {
// tooCloseCells.Add(cells[cellIndex]);
// }
// }
//}
return tooCloseCells;
}
@@ -724,13 +666,86 @@ namespace Barotrauma
foreach (GraphEdge edge in cell.edges)
{
VoronoiCell adjacent = edge.AdjacentCell(cell);
if (adjacent!=null && !newCells.Contains(adjacent)) newCells.Add(adjacent);
if (adjacent != null && !newCells.Contains(adjacent))
{
newCells.Add(adjacent);
}
}
}
return newCells;
}
private void GenerateRuin(List<VoronoiCell> mainPath)
{
Vector2 ruinSize = new Vector2(Rand.Range(5000.0f, 8000.0f, false), Rand.Range(5000.0f, 8000.0f, false));
float ruinRadius = Math.Max(ruinSize.X, ruinSize.Y) * 0.5f;
Vector2 ruinPos = cells[Rand.Int(cells.Count, false)].Center;
int iter = 0;
while (mainPath.Any(p => Vector2.Distance(ruinPos, p.Center) < ruinRadius * 2.0f))
{
Vector2 weighedPathPos = ruinPos;
iter++;
foreach (VoronoiCell pathCell in mainPath)
{
float dist = Vector2.Distance(pathCell.Center, ruinPos);
if (dist > 10000.0f) continue;
Vector2 moveAmount = Vector2.Normalize(ruinPos - pathCell.Center) * 100000.0f / dist;
//if (weighedPathPos.Y + moveAmount.Y > borders.Bottom - ruinSize.X)
//{
// moveAmount.X = (Math.Abs(moveAmount.Y) + Math.Abs(moveAmount.X))*Math.Sign(moveAmount.X);
// moveAmount.Y = 0.0f;
//}
weighedPathPos += moveAmount;
}
ruinPos = weighedPathPos;
if (iter > 10000) break;
}
VoronoiCell closestPathCell = null;
float closestDist = 0.0f;
foreach (VoronoiCell pathCell in mainPath)
{
float dist = Vector2.Distance(pathCell.Center, ruinPos);
if (closestPathCell == null || dist < closestDist)
{
closestPathCell = pathCell;
closestDist = dist;
}
}
var ruin = new Ruin(closestPathCell, cells, new Rectangle((ruinPos - ruinSize * 0.5f).ToPoint(), ruinSize.ToPoint()));
ruins = new List<Ruin>();
ruins.Add(ruin);
ruin.RuinShapes.Sort((shape1, shape2) => shape2.DistanceFromEntrance.CompareTo(shape1.DistanceFromEntrance));
for (int i = 0; i < 4; i++)
{
positionsOfInterest.Add(new InterestingPosition(ruin.RuinShapes[i].Rect.Center.ToVector2(), PositionType.Ruin));
}
foreach (RuinShape ruinShape in ruin.RuinShapes)
{
var tooClose = GetTooCloseCells(ruinShape.Rect.Center.ToVector2(), Math.Max(ruinShape.Rect.Width, ruinShape.Rect.Height));
tooClose.ForEach(c =>
{
if (c.edges.Any(e => ruinShape.Rect.Contains(e.point1) || ruinShape.Rect.Contains(e.point2))) c.CellType = CellType.Empty;
});
}
}
public Vector2 GetRandomItemPos(PositionType spawnPosType, float randomSpread, float offsetFromWall = 10.0f)
{
if (!positionsOfInterest.Any()) return Size*0.5f;
@@ -889,7 +904,7 @@ namespace Barotrauma
{
for (int i = 0; i < 2; i++)
{
wrappingWalls[side, i].Dispose();
if (wrappingWalls[side, i] != null) wrappingWalls[side, i].Dispose();
}
}

View File

@@ -0,0 +1,216 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Barotrauma
{
class LevelGenerationParams : IPropertyObject
{
private static List<LevelGenerationParams> presets;
public string Name
{
get;
private set;
}
private float width, height;
private Vector2 voronoiSiteInterval;
//how much the sites are "scattered" on x- and y-axis
//if Vector2.Zero, the sites will just be placed in a regular grid pattern
private Vector2 voronoiSiteVariance;
//how far apart the nodes of the main path can be
//x = min interval, y = max interval
private Vector2 mainPathNodeIntervalRange;
private int smallTunnelCount;
//x = min length, y = max length
private Vector2 smallTunnelLengthRange;
//how large portion of the bottom of the level should be "carved out"
//if 0.0f, the bottom will be completely solid (making the abyss unreachable)
//if 1.0f, the bottom will be completely open
private float bottomHoleProbability;
private int ruinCount;
public Color BackgroundColor
{
get;
set;
}
[HasDefaultValue(1000, false)]
public int BackgroundSpriteAmount
{
get;
set;
}
public Dictionary<string, ObjectProperty> ObjectProperties
{
get;
set;
}
[HasDefaultValue(100000.0f, false)]
public float Width
{
get { return width; }
set { width = Math.Max(value, 2000.0f); }
}
[HasDefaultValue(50000.0f, false)]
public float Height
{
get { return height; }
set { height = Math.Max(value, 2000.0f); }
}
public Vector2 VoronoiSiteInterval
{
get { return voronoiSiteInterval; }
set {
voronoiSiteInterval.X = MathHelper.Clamp(value.X, 100.0f, width/2);
voronoiSiteInterval.Y = MathHelper.Clamp(value.Y, 100.0f, height/2);
}
}
public Vector2 VoronoiSiteVariance
{
get { return voronoiSiteVariance; }
set
{
voronoiSiteVariance = new Vector2(
MathHelper.Clamp(value.X, 0, voronoiSiteInterval.X),
MathHelper.Clamp(value.Y, 0, voronoiSiteInterval.Y));
}
}
public Vector2 MainPathNodeIntervalRange
{
get { return mainPathNodeIntervalRange; }
set
{
mainPathNodeIntervalRange.X = MathHelper.Clamp(value.X, 100.0f, width / 2);
mainPathNodeIntervalRange.Y = MathHelper.Clamp(value.Y, mainPathNodeIntervalRange.X, width / 2);
}
}
[HasDefaultValue(5, false)]
public int SmallTunnelCount
{
get { return smallTunnelCount; }
set { smallTunnelCount = MathHelper.Clamp(value, 0, 100); }
}
public Vector2 SmallTunnelLengthRange
{
get { return smallTunnelLengthRange; }
set
{
smallTunnelLengthRange.X = MathHelper.Clamp(value.X, 100.0f, width);
smallTunnelLengthRange.Y = MathHelper.Clamp(value.Y, smallTunnelLengthRange.X, width);
}
}
[HasDefaultValue(1, false)]
public int RuinCount
{
get { return ruinCount; }
set { ruinCount = MathHelper.Clamp(value, 0, 10); }
}
[HasDefaultValue(0.4f, false)]
public float BottomHoleProbability
{
get { return bottomHoleProbability; }
set { bottomHoleProbability = MathHelper.Clamp(value, 0.0f, 1.0f); }
}
//public LevelGenerationParams()
//{
// Rand.SetSyncedSeed(ToolBox.StringToInt(seed));
// width = 100000.0f;
// height = 50000.0f;
// voronoiSiteInterval = 2000.0f;
// voronoiSiteVariance = new Vector2(voronoiSiteInterval, voronoiSiteInterval) * 0.4f;
// mainPathNodeIntervalRange = new Vector2(5000.0f, 10000.0f);
// float brightness = Rand.Range(1.0f, 1.3f, false);
// BackgroundColor = Color.Lerp(new Color(11, 18, 26), new Color(50, 46, 20), Rand.Range(0.0f, 1.0f, false)) * brightness;
// BackgroundColor = new Color(BackgroundColor, 1.0f);
// smallTunnelCount = 5;
// smallTunnelLengthRange = new Vector2(5000.0f, 10000.0f);
// ruinCount = 1;
// bottomHoleProbability = Rand.Range(0.1f, 0.8f, false);
// BackgroundSpriteAmount = (int)((new Vector2(width, height)).Length() / 100);
//}
public static LevelGenerationParams GetRandom(string seed)
{
Rand.SetSyncedSeed(ToolBox.StringToInt(seed));
if (presets == null || !presets.Any())
{
DebugConsole.ThrowError("Level generation presets not found - using default presets");
return new LevelGenerationParams(null);
}
return presets[Rand.Range(0, presets.Count, false)];
}
private LevelGenerationParams(XElement element)
{
Name = element==null ? "default" : element.Name.ToString();
ObjectProperties = ObjectProperty.InitProperties(this, element);
Vector3 colorVector = ToolBox.GetAttributeVector3(element, "BackgroundColor", new Vector3(50, 46, 20));
BackgroundColor = new Color((int)colorVector.X, (int)colorVector.Y, (int)colorVector.Z);
VoronoiSiteInterval = ToolBox.GetAttributeVector2(element, "VoronoiSiteInterval", new Vector2(3000, 3000));
VoronoiSiteVariance = ToolBox.GetAttributeVector2(element, "VoronoiSiteVariance", new Vector2(voronoiSiteInterval.X, voronoiSiteInterval.Y) * 0.4f);
MainPathNodeIntervalRange = ToolBox.GetAttributeVector2(element, "MainPathNodeIntervalRange", new Vector2(5000.0f, 10000.0f));
SmallTunnelLengthRange = ToolBox.GetAttributeVector2(element, "SmallTunnelLengthRange", new Vector2(5000.0f, 10000.0f));
}
public static void LoadPresets()
{
presets = new List<LevelGenerationParams>();
var files = GameMain.SelectedPackage.GetFilesOfType(ContentType.LevelGenerationPresets);
if (!files.Any())
{
files.Add("Content/Map/LevelGenerationParameters.xml");
}
foreach (string file in files)
{
XDocument doc = ToolBox.TryLoadXml(file);
if (doc == null || doc.Root == null) return;
foreach (XElement element in doc.Root.Elements())
{
presets.Add(new LevelGenerationParams(element));
}
}
}
}
}

View File

@@ -68,7 +68,9 @@ namespace Barotrauma
public void Update(float deltaTime)
{
dustOffset -= Vector2.UnitY * 10.0f * (float)deltaTime;
dustOffset -= Vector2.UnitY * 10.0f * deltaTime;
backgroundSpriteManager.Update(deltaTime);
}
public void SetWallVertices(VertexPositionTexture[] vertices)
@@ -196,7 +198,6 @@ namespace Barotrauma
public void RenderWalls(GraphicsDevice graphicsDevice, Camera cam)
{
if (wallVertices == null) return;
basicEffect.World = cam.ShaderTransform

View File

@@ -201,6 +201,8 @@ namespace Voronoi2
public bool isSolid;
public bool OutsideLevel;
public Vector2 Center
{
get { return (point1 + point2) / 2.0f; }
@@ -216,10 +218,25 @@ namespace Voronoi2
{
return cell1;
}
else
return null;
}
/// <summary>
/// Returns the normal of the edge that points outwards from the specified cell
/// </summary>
public Vector2 GetNormal(VoronoiCell cell)
{
Vector2 dir = Vector2.Normalize(point1 - point2);
Vector2 normal = new Vector2(dir.Y, -dir.X);
if (cell != null && Vector2.Dot(normal, Vector2.Normalize(Center - cell.Center)) < 0)
{
return null;
normal = -normal;
}
return normal;
}
}

View File

@@ -48,28 +48,16 @@ namespace Barotrauma
get { return midPos; }
}
public WrappingWall(List<VoronoiCell> pathCells, List<VoronoiCell> mapCells, float maxY, int dir = -1)
public WrappingWall(List<VoronoiCell> pathCells, List<VoronoiCell> mapCells, Rectangle ignoredArea, int dir = -1)
{
cells = new List<VoronoiCell>();
VoronoiCell lowestPathCell = null;
foreach (VoronoiCell pathCell in pathCells)
{
if (lowestPathCell == null || pathCell.Center.Y < lowestPathCell.Center.Y)
{
lowestPathCell = pathCell;
}
}
float bottomY = Math.Max(lowestPathCell.Center.Y, maxY);
VoronoiCell edgeCell = null;
foreach (VoronoiCell cell in mapCells)
{
if (cell.Center.Y > bottomY) continue;
if (edgeCell == null
|| (dir < 0 && cell.Center.X < edgeCell.Center.X)
|| (dir > 0 && cell.Center.X > edgeCell.Center.X))
if (ignoredArea.Contains(cell.Center)) continue;
if (Math.Sign(cell.Center.X - ignoredArea.Center.X) != Math.Sign(dir)) continue;
if (edgeCell == null || cell.Center.Y < edgeCell.Center.Y)
{
edgeCell = cell;
}

View File

@@ -61,8 +61,8 @@ namespace Barotrauma
}
public static object GetAttributeObject(XElement element, string name)
{
if (element.Attribute(name) == null) return null;
{
if (element == null || element.Attribute(name) == null) return null;
return GetAttributeObject(element.Attribute(name));
}
@@ -106,7 +106,7 @@ namespace Barotrauma
public static string GetAttributeString(XElement element, string name, string defaultValue)
{
if (element.Attribute(name) == null) return defaultValue;
if (element == null || element.Attribute(name) == null) return defaultValue;
return GetAttributeString(element.Attribute(name), defaultValue);
}
@@ -119,7 +119,7 @@ namespace Barotrauma
public static float GetAttributeFloat(XElement element, string name, float defaultValue)
{
if (element.Attribute(name) == null) return defaultValue;
if (element == null || element.Attribute(name) == null) return defaultValue;
float val = defaultValue;
@@ -158,7 +158,7 @@ namespace Barotrauma
public static int GetAttributeInt(XElement element, string name, int defaultValue)
{
if (element.Attribute(name) == null) return defaultValue;
if (element == null || element.Attribute(name) == null) return defaultValue;
int val = defaultValue;
@@ -176,10 +176,9 @@ namespace Barotrauma
public static bool GetAttributeBool(XElement element, string name, bool defaultValue)
{
var attribute = element.Attribute(name);
if (attribute == null) return defaultValue;
if (element == null || element.Attribute(name) == null) return defaultValue;
return GetAttributeBool(attribute, defaultValue);
return GetAttributeBool(element.Attribute(name), defaultValue);
}
public static bool GetAttributeBool(XAttribute attribute, bool defaultValue)
@@ -206,16 +205,25 @@ namespace Barotrauma
public static Vector2 GetAttributeVector2(XElement element, string name, Vector2 defaultValue)
{
if (element.Attribute(name) == null) return defaultValue;
if (element == null || element.Attribute(name) == null) return defaultValue;
string val = element.Attribute(name).Value;
return ParseToVector2(val);
}
public static Vector3 GetAttributeVector3(XElement element, string name, Vector3 defaultValue)
{
if (element == null || element.Attribute(name) == null) return defaultValue;
string val = element.Attribute(name).Value;
return ParseToVector3(val);
}
public static Vector4 GetAttributeVector4(XElement element, string name, Vector4 defaultValue)
{
if (element.Attribute(name) == null) return defaultValue;
if (element == null || element.Attribute(name) == null) return defaultValue;
string val = element.Attribute(name).Value;
@@ -259,6 +267,26 @@ namespace Barotrauma
return vector.X.ToString("G", CultureInfo.InvariantCulture) + "," + vector.Y.ToString("G", CultureInfo.InvariantCulture);
}
public static Vector3 ParseToVector3(string stringVector3, bool errorMessages = true)
{
string[] components = stringVector3.Split(',');
Vector3 vector = Vector3.Zero;
if (components.Length!=3)
{
if (!errorMessages) return vector;
DebugConsole.ThrowError("Failed to parse the string ''"+stringVector3+"'' to Vector3");
return vector;
}
float.TryParse(components[0], NumberStyles.Any, CultureInfo.InvariantCulture, out vector.X);
float.TryParse(components[1], NumberStyles.Any, CultureInfo.InvariantCulture, out vector.Y);
float.TryParse(components[2], NumberStyles.Any, CultureInfo.InvariantCulture, out vector.Z);
return vector;
}
public static Vector4 ParseToVector4(string stringVector4, bool errorMessages = true)
{
string[] components = stringVector4.Split(',');