From 9b15d2f8948e3a52cfd67a72ae4f8ba7a92fe45c Mon Sep 17 00:00:00 2001 From: Regalis Date: Tue, 27 Sep 2016 20:18:55 +0300 Subject: [PATCH] Improved background sprite placement logic: orientation of the cell edges determined by their normals instead of their position relative to the cell --- .../BackgroundSpritePrefabs.xml | 11 +++- .../BackgroundSpriteManager.cs | 66 ++++++++++--------- .../Source/Map/Levels/VoronoiElements.cs | 19 +++++- 3 files changed, 59 insertions(+), 37 deletions(-) diff --git a/Subsurface/Content/BackgroundSprites/BackgroundSpritePrefabs.xml b/Subsurface/Content/BackgroundSprites/BackgroundSpritePrefabs.xml index f22412c22..033a80b77 100644 --- a/Subsurface/Content/BackgroundSprites/BackgroundSpritePrefabs.xml +++ b/Subsurface/Content/BackgroundSprites/BackgroundSpritePrefabs.xml @@ -1,11 +1,11 @@  - + - + @@ -35,9 +35,14 @@ - + + + + + + diff --git a/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpriteManager.cs b/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpriteManager.cs index b99738e9f..d6ff2000c 100644 --- a/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpriteManager.cs +++ b/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpriteManager.cs @@ -86,36 +86,35 @@ namespace Barotrauma { 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), @@ -127,43 +126,46 @@ namespace Barotrauma VoronoiCell cell = cells[Rand.Int(cells.Count, false)]; List edges = new List(); + List normals = new List(); foreach (GraphEdge edge in cell.edges) { if (!edge.isSolid || edge.OutsideLevel) continue; + + Vector2 normal = edge.GetNormal(cell); - if (prefab.Alignment.HasFlag(Alignment.Bottom) && - Math.Abs(edge.point1.X - edge.point2.X) < Math.Abs(edge.point1.Y - edge.point2.Y)) - { - if (edge.Center.Y < cell.Center.Y) edges.Add(edge); - } - else if (prefab.Alignment.HasFlag(Alignment.Top) && - Math.Abs(edge.point1.X - edge.point2.X) < Math.Abs(edge.point1.Y - edge.point2.Y)) - { - 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); + Vector2 pos = closestEdge.point2 + dir * Rand.Range(prefab.Sprite.size.X / 2.0f, length - prefab.Sprite.size.X / 2.0f, false); return pos; } diff --git a/Subsurface/Source/Map/Levels/VoronoiElements.cs b/Subsurface/Source/Map/Levels/VoronoiElements.cs index 1f5aaff73..67e527240 100644 --- a/Subsurface/Source/Map/Levels/VoronoiElements.cs +++ b/Subsurface/Source/Map/Levels/VoronoiElements.cs @@ -218,10 +218,25 @@ namespace Voronoi2 { return cell1; } - else + + return null; + } + + /// + /// Returns the normal of the edge that points outwards from the specified cell + /// + 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; } }