From dd46ce1d98275f582e13c9875bedbc2e45bd4b04 Mon Sep 17 00:00:00 2001 From: Regalis Date: Tue, 20 Dec 2016 16:11:47 +0200 Subject: [PATCH] Adjusting submarine spawnposition if the sub (or any docked subs) intersect with walls --- Subsurface/Source/GameSession/GameSession.cs | 2 +- Subsurface/Source/Map/Submarine.cs | 62 ++++++++++++++++++++ Subsurface/Source/Utils/MathUtils.cs | 31 ++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) diff --git a/Subsurface/Source/GameSession/GameSession.cs b/Subsurface/Source/GameSession/GameSession.cs index eb707dfbe..362e0f5e0 100644 --- a/Subsurface/Source/GameSession/GameSession.cs +++ b/Subsurface/Source/GameSession/GameSession.cs @@ -200,7 +200,7 @@ namespace Barotrauma { level.Generate(); - submarine.SetPosition(level.StartPosition - new Vector2(0.0f, 2000.0f)); + submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition - new Vector2(0.0f, 2000.0f))); //secondSub.SetPosition(level.EndPosition - new Vector2(0.0f, 2000.0f)); diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index beeb06bd7..b94c8f70f 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -11,6 +11,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Xml.Linq; +using Voronoi2; namespace Barotrauma { @@ -311,6 +312,67 @@ namespace Barotrauma dockedBorders.Y += dockedBorders.Height; return dockedBorders; } + + public Vector2 FindSpawnPos(Vector2 spawnPos) + { + Rectangle dockedBorders = GetDockedBorders(); + + int iterations = 0; + bool wallTooClose = false; + do + { + Rectangle worldBorders = new Rectangle( + dockedBorders.X + (int)spawnPos.X, + dockedBorders.Y + (int)spawnPos.Y, + dockedBorders.Width, + dockedBorders.Height); + + wallTooClose = false; + + var nearbyCells = Level.Loaded.GetCells( + spawnPos, (int)Math.Ceiling(Math.Max(dockedBorders.Width, dockedBorders.Height) / (float)Level.GridCellSize)); + + foreach (VoronoiCell cell in nearbyCells) + { + if (cell.CellType == CellType.Empty) continue; + + foreach (GraphEdge e in cell.edges) + { + List intersections = MathUtils.GetLineRectangleIntersections(e.point1, e.point2, worldBorders); + foreach (Vector2 intersection in intersections) + { + wallTooClose = true; + + if (intersection.X < spawnPos.X) + { + spawnPos.X += intersection.X - worldBorders.X; + } + else + { + spawnPos.X += intersection.X - worldBorders.Right; + } + + if (intersection.Y < spawnPos.Y) + { + spawnPos.Y += intersection.Y - (worldBorders.Y - worldBorders.Height); + } + else + { + spawnPos.Y += intersection.Y - worldBorders.Y; + } + + spawnPos.Y = Math.Min(spawnPos.Y, Level.Loaded.Size.Y - dockedBorders.Height / 2); + } + } + } + + iterations++; + } while (wallTooClose && iterations < 10); + + return spawnPos; + + + } //drawing ---------------------------------------------------- diff --git a/Subsurface/Source/Utils/MathUtils.cs b/Subsurface/Source/Utils/MathUtils.cs index f194bbc09..ccdf61cc5 100644 --- a/Subsurface/Source/Utils/MathUtils.cs +++ b/Subsurface/Source/Utils/MathUtils.cs @@ -233,6 +233,37 @@ namespace Barotrauma new Vector2(rect.Right, rect.Y - rect.Height)); } + public static List GetLineRectangleIntersections(Vector2 a1, Vector2 a2, Rectangle rect) + { + List intersections = new List(); + + Vector2? intersection = GetLineIntersection(a1, a2, + new Vector2(rect.X, rect.Y), + new Vector2(rect.Right, rect.Y)); + + if (intersection != null) intersections.Add((Vector2)intersection); + + intersection = GetLineIntersection(a1, a2, + new Vector2(rect.X, rect.Y - rect.Height), + new Vector2(rect.Right, rect.Y - rect.Height)); + + if (intersection != null) intersections.Add((Vector2)intersection); + + intersection = GetLineIntersection(a1, a2, + new Vector2(rect.X, rect.Y), + new Vector2(rect.X, rect.Y - rect.Height)); + + if (intersection != null) intersections.Add((Vector2)intersection); + + intersection = GetLineIntersection(a1, a2, + new Vector2(rect.Right, rect.Y), + new Vector2(rect.Right, rect.Y - rect.Height)); + + if (intersection != null) intersections.Add((Vector2)intersection); + + return intersections; + } + public static float LineToPointDistance(Vector2 lineA, Vector2 lineB, Vector2 point) { float xDiff = lineB.X - lineA.X;