diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj index a798b157a..42058a519 100644 --- a/Subsurface/Barotrauma.csproj +++ b/Subsurface/Barotrauma.csproj @@ -320,9 +320,15 @@ PreserveNewest + + PreserveNewest + PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Subsurface/Content/BackgroundSprites/BackgroundSpritePrefabs.xml b/Subsurface/Content/BackgroundSprites/BackgroundSpritePrefabs.xml index b132e1b6f..be3735b03 100644 --- a/Subsurface/Content/BackgroundSprites/BackgroundSpritePrefabs.xml +++ b/Subsurface/Content/BackgroundSprites/BackgroundSpritePrefabs.xml @@ -1,20 +1,34 @@  - - + + - + - + - - + + - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Subsurface/Content/BackgroundSprites/ice.png b/Subsurface/Content/BackgroundSprites/ice.png new file mode 100644 index 000000000..9e3b36a02 Binary files /dev/null and b/Subsurface/Content/BackgroundSprites/ice.png differ diff --git a/Subsurface/Content/BackgroundSprites/vegetation.png b/Subsurface/Content/BackgroundSprites/vegetation.png index c104f8594..9c4c1937b 100644 Binary files a/Subsurface/Content/BackgroundSprites/vegetation.png and b/Subsurface/Content/BackgroundSprites/vegetation.png differ diff --git a/Subsurface/Content/BackgroundSprites/vegetation2.png b/Subsurface/Content/BackgroundSprites/vegetation2.png new file mode 100644 index 000000000..c0383a41d Binary files /dev/null and b/Subsurface/Content/BackgroundSprites/vegetation2.png differ diff --git a/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpriteManager.cs b/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpriteManager.cs index ba2692d94..347453cfb 100644 --- a/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpriteManager.cs +++ b/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpriteManager.cs @@ -2,6 +2,7 @@ using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Xml.Linq; @@ -14,21 +15,33 @@ namespace Barotrauma public readonly BackgroundSpritePrefab Prefab; public Vector2 Position; - public BackgroundSprite(BackgroundSpritePrefab prefab, Vector2 position) + public float Scale; + + public float Rotation; + + public BackgroundSprite(BackgroundSpritePrefab prefab, Vector2 position, float scale, float rotation = 0.0f) { this.Prefab = prefab; this.Position = position; + + this.Scale = scale; + + this.Rotation = rotation; } } class BackgroundSpriteManager { + const int GridSize = 1000; + private List prefabs; - private List sprites; + //private List sprites; + + private List[,] sprites; public BackgroundSpriteManager(string configPath) { - sprites = new List(); + //sprites = new List[2,2](); prefabs = new List(); XDocument doc = ToolBox.TryLoadXml(configPath); @@ -42,82 +55,166 @@ namespace Barotrauma public void PlaceSprites(Level level, int amount) { - sprites.Clear(); + sprites = new List[ + (int)Math.Ceiling(level.Size.X / GridSize), + (int)Math.Ceiling(level.Size.Y / GridSize)]; - for (int i = 0 ; i (); + } + } + + for (int i = 0 ; i < amount; i++) { BackgroundSpritePrefab prefab = GetRandomPrefab(); - Vector2? pos = FindSpritePosition(level, prefab); + GraphEdge selectedEdge = null; + Vector2? pos = FindSpritePosition(level, prefab, out selectedEdge); if (pos == null) continue; - var newSprite = new BackgroundSprite(prefab, (Vector2)pos); - - int n = 0; - - while (n < sprites.Count) + float rotation = 0.0f; + if (prefab.AlignWithSurface) { - n++; + Vector2 leftPoint = selectedEdge.point2; + Vector2 rightPoint = selectedEdge.point1; - Sprite existingSprite = sprites[n - 1].Prefab.Sprite; - if (existingSprite == null) continue; - if (existingSprite.Texture == newSprite.Prefab.Sprite.Texture) break; + //if (leftPoint.X > rightPoint.X) + //{ + // leftPoint = selectedEdge.point2; + // rightPoint = selectedEdge.point1; + //} + + rotation = -MathUtils.VectorToAngle(rightPoint - leftPoint); } - sprites.Insert(n, newSprite); + 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), rotation); + + int n = 0; + + int x = (int)Math.Floor(((Vector2)pos).X / GridSize); + if (x<0 || x >= sprites.GetLength(0)) continue; + int y = (int)Math.Floor(((Vector2)pos).Y / GridSize); + if (y<0 || 1 >= sprites.GetLength(1)) continue; + + sprites[x,y].Add(newSprite); + + //while (n < sprites.Count) + //{ + // n++; + + // Sprite existingSprite = sprites[n - 1].Prefab.Sprite; + // if (existingSprite == null) continue; + // if (existingSprite.Texture == newSprite.Prefab.Sprite.Texture) break; + //} + + //sprites.Insert(n, newSprite); } } - private Vector2? FindSpritePosition(Level level, BackgroundSpritePrefab prefab) + private Vector2? FindSpritePosition(Level level, BackgroundSpritePrefab prefab, out GraphEdge closestEdge) { + closestEdge = null; + Vector2 randomPos = new Vector2(Rand.Range(0.0f, level.Size.X, false), Rand.Range(0.0f, level.Size.Y, false)); var cells = level.GetCells(randomPos); if (!cells.Any()) return null; VoronoiCell cell = cells[Rand.Int(cells.Count, false)]; - GraphEdge bestEdge = null; + List edges = new List(); foreach (GraphEdge edge in cell.edges) { + if (!edge.isSolid) continue; + if (prefab.Alignment.HasFlag(Alignment.Bottom)) { - if (bestEdge == null || edge.Center.Y > bestEdge.Center.Y) bestEdge = edge; + 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 (bestEdge == null || edge.Center.Y < bestEdge.Center.Y) bestEdge = edge; + 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 (bestEdge == null || edge.Center.X > bestEdge.Center.X) bestEdge = edge; + if (edge.Center.X < cell.Center.X) edges.Add(edge); } else if (prefab.Alignment.HasFlag(Alignment.Right)) { - if (bestEdge == null || edge.Center.X < bestEdge.Center.X) bestEdge = edge; + if (edge.Center.X > cell.Center.X) edges.Add(edge); + } + else + { + edges.Add(edge); } } - Vector2 dir = Vector2.Normalize(bestEdge.point1 - bestEdge.point2); - Vector2 pos = bestEdge.Center; + if (!edges.Any()) return null; - if (prefab.Alignment.HasFlag(Alignment.Bottom)) + closestEdge = edges[Rand.Int(edges.Count,false)]; + + 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); + + if (prefab.Alignment.HasFlag(Alignment.Top)) { - pos.Y -= Math.Abs(dir.Y) * prefab.Sprite.size.X/Math.Abs(dir.X); + pos.Y -= Math.Abs(dir.Y) * prefab.Sprite.size.X / Math.Abs(dir.X); } - else if (prefab.Alignment.HasFlag(Alignment.Top)) + else if (prefab.Alignment.HasFlag(Alignment.Bottom)) { - pos.Y += Math.Abs(dir.Y) * prefab.Sprite.size.X/Math.Abs(dir.X); + pos.Y += Math.Abs(dir.Y) * prefab.Sprite.size.X / Math.Abs(dir.X); } return pos; } - public void DrawSprites(SpriteBatch spriteBatch) + public void DrawSprites(SpriteBatch spriteBatch, Camera cam) { - foreach (BackgroundSprite sprite in sprites) + Stopwatch sw = new Stopwatch(); + sw.Start(); + + Rectangle indices = Rectangle.Empty; + indices.X = (int)Math.Floor(cam.WorldView.X / (float)GridSize) - 1; + if (indices.X >= sprites.GetLength(0)) return; + + indices.Y = (int)Math.Floor((cam.WorldView.Y - cam.WorldView.Height) / (float)GridSize) - 1; + if (indices.Y >= sprites.GetLength(1)) return; + + + indices.Width = (int)Math.Ceiling(cam.WorldView.Right / (float)GridSize) + 1; + if (indices.Width < 0) return; + indices.Height = (int)Math.Ceiling(cam.WorldView.Y / (float)GridSize) + 1; + if (indices.Height < 0) return; + + indices.X = Math.Max(indices.X, 0); + indices.Y = Math.Max(indices.Y, 0); + indices.Width = Math.Min(indices.Width, sprites.GetLength(0)); + indices.Height = Math.Min(indices.Height, sprites.GetLength(1)); + + float z = 0.0f; + for (int x = indices.X; x < indices.Width; x++) { - sprite.Prefab.Sprite.Draw(spriteBatch, new Vector2(sprite.Position.X, -sprite.Position.Y)); + for (int y = indices.Y; y < indices.Height; y++) + { + 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); + z += 0.0001f; + } + } } + + sw.Stop(); + Debug.WriteLine(sw.ElapsedMilliseconds + " - "+sw.ElapsedTicks); } private BackgroundSpritePrefab GetRandomPrefab() diff --git a/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpritePrefab.cs b/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpritePrefab.cs index 7767e727e..8fe9c8021 100644 --- a/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpritePrefab.cs +++ b/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpritePrefab.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.Xna.Framework; +using System; using System.Xml.Linq; namespace Barotrauma @@ -9,6 +10,12 @@ namespace Barotrauma public readonly Alignment Alignment; + public readonly Vector2 Scale; + + public readonly bool AlignWithSurface; + + public readonly Vector2 RandomRotation; + public readonly int Commonness; public BackgroundSpritePrefab(XElement element) @@ -19,6 +26,15 @@ namespace Barotrauma Commonness = ToolBox.GetAttributeInt(element, "commonness", 1); + Scale.X = ToolBox.GetAttributeFloat(element, "minsize", 1.0f); + Scale.Y = ToolBox.GetAttributeFloat(element, "maxsize", 1.0f); + + AlignWithSurface = ToolBox.GetAttributeBool(element, "alignwithsurface", false); + + RandomRotation = ToolBox.GetAttributeVector2(element, "randomrotation", Vector2.Zero); + RandomRotation.X = MathHelper.ToRadians(RandomRotation.X); + RandomRotation.Y = MathHelper.ToRadians(RandomRotation.Y); + foreach (XElement subElement in element.Elements()) { if (subElement.Name.ToString().ToLower() != "sprite") continue; diff --git a/Subsurface/Source/Map/Levels/CaveGenerator.cs b/Subsurface/Source/Map/Levels/CaveGenerator.cs index ee789b836..df04cc499 100644 --- a/Subsurface/Source/Map/Levels/CaveGenerator.cs +++ b/Subsurface/Source/Map/Levels/CaveGenerator.cs @@ -40,7 +40,9 @@ namespace Barotrauma { for (float y = edges.Y + sideInterval; y < edges.W - sideInterval; y += sideInterval) { - sites.Add(new Vector2(x, y) + Rand.Vector(sideInterval*0.45f, false)); + if (Rand.Int(10, false) == 0) continue; + + sites.Add(new Vector2(x, y) + Rand.Vector(sideInterval*0.4f, false)); } } @@ -76,6 +78,8 @@ namespace Barotrauma float closestDist = 0.0f; foreach (VoronoiCell cell in newCells) { + if (cell.CellType != CellType.Edge) continue; + float dist = Vector2.Distance(startPoint, cell.Center); if (dist < closestDist || startCell == null) { @@ -87,27 +91,62 @@ namespace Barotrauma startCell.CellType = CellType.Path; List path = new List() {startCell}; - //VoronoiCell pathCell = startCell; - //for (int i = 0; i < newCells.Count / 2; i++) - //{ + VoronoiCell pathCell = startCell; + for (int i = 0; i < newCells.Count / 2; i++) + { - // var allowdNextCells = new List(); - // foreach (GraphEdge edge in pathCell.edges) - // { - // var adjacent = edge.AdjacentCell(pathCell); - // if (adjacent == null || - // adjacent.CellType == CellType.Path || - // adjacent.CellType == CellType.Removed || - // adjacent.CellType == CellType.Edge) continue; + var allowedNextCells = new List(); + foreach (GraphEdge edge in pathCell.edges) + { + var adjacent = edge.AdjacentCell(pathCell); + if (adjacent == null || + //adjacent.CellType == CellType.Path || + adjacent.CellType == CellType.Removed || + adjacent.CellType == CellType.Edge) continue; - // allowdNextCells.Add(adjacent); - // } + allowedNextCells.Add(adjacent); + } + + if (allowedNextCells.Count == 0) break; - // if (allowdNextCells.Count == 0) break; + pathCell = allowedNextCells[Rand.Int(allowedNextCells.Count, false)]; + if (Rand.Int(4,false)==0) + { + float furthestDist = 0.0f; + foreach (VoronoiCell nextCell in allowedNextCells) + { + float dist = Vector2.Distance(startCell.Center, nextCell.Center); + if (dist > furthestDist || furthestDist == 0.0f) + { + furthestDist = dist; + pathCell = nextCell; + } + } + } - // pathCell = allowdNextCells[Rand.Int(allowdNextCells.Count, false)]; - // path.Add(pathCell); - //} + pathCell.CellType = CellType.Path; + path.Add(pathCell); + } + + float minPathWidth = 100.0f; + for (int i = 0; i < path.Count; i++) + { + var cell = path[i]; + foreach (GraphEdge edge in cell.edges) + { + if (edge.point1 == edge.point2) continue; + if (Vector2.Distance(edge.point1, edge.point2) > minPathWidth) continue; + + + GraphEdge adjacentEdge = cell.edges.Find(e => e != edge && (e.point1 == edge.point1 || e.point2 == edge.point1)); + + var adjacentCell = adjacentEdge.AdjacentCell(cell); + if (i>0 && (adjacentCell.CellType == CellType.Path || adjacentCell.CellType == CellType.Edge)) continue; + + adjacentCell.CellType = CellType.Path; + path.Add(adjacentCell); + } + } return path; } diff --git a/Subsurface/Source/Map/Levels/Level.cs b/Subsurface/Source/Map/Levels/Level.cs index c5e99c239..6273ba528 100644 --- a/Subsurface/Source/Map/Levels/Level.cs +++ b/Subsurface/Source/Map/Levels/Level.cs @@ -310,47 +310,58 @@ namespace Barotrauma foreach (VoronoiCell cell in pathCells) { + cell.CellType = CellType.Path; cells.Remove(cell); } - //for (int i = 0; i < 3; i++) - //{ - // Vector2 startPoint = Vector2.Zero; - // VoronoiCell startCell = null; - // while (true) - // { - // startCell = cells[Rand.Int(cells.Count, false)]; + List usedCaveCells = new List(); + for (int i = 0; i < 3; i++) + { + Vector2 startPoint = Vector2.Zero; + VoronoiCell startCell = null; - // GraphEdge startEdge = - // startCell.edges.Find(e => pathCells.Contains(e.AdjacentCell(startCell))); + var caveCells = new List(); - // if (startEdge != null) - // { - // startPoint = (startEdge.point1 + startEdge.point2) / 2.0f; - // break; - // } - // } - - // var caveCells = GetCells(startCell.Center, 1); + while (true) + { + startCell = cells[Rand.Int(cells.Count, false)]; - // List caveSolidCells; + GraphEdge startEdge = + startCell.edges.Find(e => pathCells.Contains(e.AdjacentCell(startCell))); - // var cavePathCells = CaveGenerator.CarveCave(caveCells, startPoint, out caveSolidCells); + if (startEdge != null) + { + startPoint = (startEdge.point1 + startEdge.point2) / 2.0f; + startPoint += startPoint - startCell.Center; - // caveCells.ForEach(c => cells.Remove(c)); + caveCells = GetCells(startCell.Center, 2); + caveCells.RemoveAll(c => c.CellType == CellType.Path); - // //caveSolidCells = CleanCells(cavePathCells); + if (usedCaveCells.Any(c => caveCells.Contains(c))) continue; + break; + } + } - // cells.AddRange(caveSolidCells); + usedCaveCells.AddRange(caveCells); - // foreach (VoronoiCell cell in cavePathCells) - // { - // cells.Remove(cell); - // } + List caveSolidCells; - // pathCells.AddRange(cavePathCells); - //} + var cavePathCells = CaveGenerator.CarveCave(caveCells, startPoint, out caveSolidCells); + + caveCells.ForEach(c => cells.Remove(c)); + + //caveSolidCells = CleanCells(cavePathCells); + + cells.AddRange(caveSolidCells); + + foreach (VoronoiCell cell in cavePathCells) + { + cells.Remove(cell); + } + + pathCells.AddRange(cavePathCells); + } for (int x = 0; x < cellGrid.GetLength(0); x++) { @@ -376,6 +387,7 @@ namespace Barotrauma renderer.SetBodyVertices(bodyVertices.ToArray()); renderer.SetWallVertices(CaveGenerator.GenerateWallShapes(cells)); + renderer.PlaceSprites(1000); wrappingWalls = new WrappingWall[2, 2]; @@ -442,7 +454,6 @@ namespace Barotrauma endPosition = temp; } - renderer.PlaceSprites(100); Debug.WriteLine("**********************************************************************************"); Debug.WriteLine("Generated a map with " + sites.Count + " sites in " + sw.ElapsedMilliseconds + " ms"); diff --git a/Subsurface/Source/Map/Levels/LevelRenderer.cs b/Subsurface/Source/Map/Levels/LevelRenderer.cs index fe526f726..21af54e53 100644 --- a/Subsurface/Source/Map/Levels/LevelRenderer.cs +++ b/Subsurface/Source/Map/Levels/LevelRenderer.cs @@ -120,7 +120,7 @@ namespace Barotrauma SamplerState.LinearWrap, DepthStencilState.Default, null, null, cam.Transform); - backgroundSpriteManager.DrawSprites(spriteBatch); + backgroundSpriteManager.DrawSprites(spriteBatch, cam); if (backgroundCreatureManager!=null) backgroundCreatureManager.Draw(spriteBatch);