From 859be53d283624ad5ef5fdea262b9ff8bc4341a1 Mon Sep 17 00:00:00 2001 From: Regalis Date: Mon, 14 Dec 2015 18:59:59 +0200 Subject: [PATCH] Level wall generation bugfixes, moved level background drawing to LevelRenderer, more coordinate system bugfixes, better looking progress bars, --- Subsurface/Content/UI/style.xml | 13 +- Subsurface/Source/Camera.cs | 2 +- Subsurface/Source/Characters/Character.cs | 39 +++-- Subsurface/Source/Characters/CharacterHUD.cs | 8 +- Subsurface/Source/DebugConsole.cs | 2 +- Subsurface/Source/Events/MonsterEvent.cs | 2 +- .../Source/Events/Quests/MonsterQuest.cs | 2 +- Subsurface/Source/GUI/GUIProgressBar.cs | 37 ++++- .../GameSession/GameModes/TutorialMode.cs | 2 +- Subsurface/Source/Items/Components/Door.cs | 2 +- .../Items/Components/Holdable/Propulsion.cs | 2 +- .../Items/Components/Signal/LightComponent.cs | 4 +- Subsurface/Source/Map/Hull.cs | 10 +- Subsurface/Source/Map/Levels/Level.cs | 86 +++++------ Subsurface/Source/Map/Levels/LevelRenderer.cs | 134 +++++++++++++++--- Subsurface/Source/Map/Levels/WrappingWall.cs | 4 +- Subsurface/Source/Map/Lights/ConvexHull.cs | 8 +- Subsurface/Source/Map/LocationType.cs | 7 +- Subsurface/Source/Map/Structure.cs | 6 +- Subsurface/Source/Map/Submarine.cs | 29 +--- Subsurface/Source/Map/SubmarineBody.cs | 21 +-- Subsurface/Source/Map/WayPoint.cs | 6 + Subsurface/Source/Screens/EditMapScreen.cs | 2 + Subsurface/Source/Screens/GameScreen.cs | 77 ++-------- Subsurface/Source/Screens/LobbyScreen.cs | 3 +- Subsurface/Source/Screens/NetLobbyScreen.cs | 41 ++++-- Subsurface/Source/Screens/ServerListScreen.cs | 1 - Subsurface_Solution.v12.suo | Bin 788480 -> 803328 bytes 28 files changed, 318 insertions(+), 232 deletions(-) diff --git a/Subsurface/Content/UI/style.xml b/Subsurface/Content/UI/style.xml index 0a0b09c89..0f7a74e6e 100644 --- a/Subsurface/Content/UI/style.xml +++ b/Subsurface/Content/UI/style.xml @@ -9,8 +9,7 @@ hovercolor="0.8, 0.8, 0.8, 1.0" selectedcolor="1.0, 0.82, 0.05, 1.0" - outlinecolor="0.5, 0.57, 0.6, 1.0"> - + outlinecolor="0.5, 0.57, 0.6, 1.0"> + + + \ No newline at end of file diff --git a/Subsurface/Source/Camera.cs b/Subsurface/Source/Camera.cs index e4d4e20bf..c17ff9d94 100644 --- a/Subsurface/Source/Camera.cs +++ b/Subsurface/Source/Camera.cs @@ -174,7 +174,7 @@ namespace Barotrauma if (PlayerInput.KeyDown(Keys.S)) moveCam.Y -= moveSpeed; if (PlayerInput.KeyDown(Keys.W)) moveCam.Y += moveSpeed; - if (Submarine.Loaded!=null) + if (Submarine.Loaded!=null && Screen.Selected == GameMain.GameScreen) { moveCam += FarseerPhysics.ConvertUnits.ToDisplayUnits(Submarine.Loaded.Velocity*deltaTime); } diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index fe249eae7..bad2d1bc4 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -733,7 +733,7 @@ namespace Barotrauma { Limb head = AnimController.GetLimb(LimbType.Head); - Lights.LightManager.ViewPos = DrawPosition; + //Lights.LightManager.ViewPos = WorldPosition; if (!DisableControls) { @@ -1327,10 +1327,14 @@ namespace Barotrauma message.Write(AnimController.Dir > 0.0f); } - if ((AnimController.RefLimb.SimPosition - Submarine.Loaded.SimPosition).Length() > NetConfig.CharacterIgnoreDistance) return true; - - message.Write(AnimController.RefLimb.SimPosition.X); - message.Write(AnimController.RefLimb.SimPosition.Y); + message.Write(Submarine != null); + + //Vector2 position = Submarine == null ? SimPosition : SimPosition - Submarine.SimPosition; + + //if ((AnimController.RefLimb.SimPosition - Submarine.Loaded.SimPosition).Length() > NetConfig.CharacterIgnoreDistance) return true; + + message.Write(SimPosition.X); + message.Write(SimPosition.Y); return true; default: @@ -1495,17 +1499,21 @@ namespace Barotrauma #endif return; } - try - { - pos.X = message.ReadFloat(); - pos.Y = message.ReadFloat(); - } - catch + bool inSub = message.ReadBoolean(); + + pos.X = message.ReadFloat(); + pos.Y = message.ReadFloat(); + + if (inSub) { - //failed to read position, Character may be further than NetConfig.CharacterIgnoreDistance - pos = SimPosition; - } + Hull newHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(pos), AnimController.CurrentHull, false); + if (newHull != null) + { + AnimController.CurrentHull = newHull; + Submarine = newHull.Submarine; + } + } if (secondaryKeyState) { @@ -1517,7 +1525,8 @@ namespace Barotrauma cursorPosition = Position + new Vector2(1000.0f, 0.0f) * dir; } - AnimController.RefLimb.body.TargetPosition = AnimController.EstimateCurrPosition(pos, (float)(NetTime.Now + message.SenderConnection.RemoteTimeOffset) - sendingTime); + AnimController.RefLimb.body.TargetPosition = + AnimController.EstimateCurrPosition(pos, (float)(NetTime.Now + message.SenderConnection.RemoteTimeOffset) - sendingTime); LastNetworkUpdate = sendingTime; diff --git a/Subsurface/Source/Characters/CharacterHUD.cs b/Subsurface/Source/Characters/CharacterHUD.cs index ed61c57fd..6ffbf8868 100644 --- a/Subsurface/Source/Characters/CharacterHUD.cs +++ b/Subsurface/Source/Characters/CharacterHUD.cs @@ -54,7 +54,7 @@ namespace Barotrauma if (character.ClosestCharacter != null && (character.ClosestCharacter.IsDead || character.ClosestCharacter.Stun > 0.0f)) { - Vector2 startPos = character.Position + (character.ClosestCharacter.WorldPosition - character.WorldPosition) * 0.7f; + Vector2 startPos = character.DrawPosition + (character.ClosestCharacter.DrawPosition - character.DrawPosition) * 0.7f; startPos = cam.WorldToScreen(startPos); Vector2 textPos = startPos; @@ -67,7 +67,7 @@ namespace Barotrauma else if (character.SelectedCharacter == null && character.ClosestItem != null && character.SelectedConstruction == null) { - Vector2 startPos = character.WorldPosition + (character.ClosestItem.WorldPosition - character.WorldPosition) * 0.7f; + Vector2 startPos = character.DrawPosition + (character.ClosestItem.DrawPosition - character.DrawPosition) * 0.7f; startPos = cam.WorldToScreen(startPos); Vector2 textPos = startPos; @@ -96,10 +96,10 @@ namespace Barotrauma { int width = 100, height = 20; - drowningBar = new GUIProgressBar(new Rectangle(30, GameMain.GraphicsHeight - 200, width, height), Color.Blue, 1.0f); + drowningBar = new GUIProgressBar(new Rectangle(30, GameMain.GraphicsHeight - 200, width, height), Color.Blue, GUI.Style, 1.0f, Alignment.TopLeft); new GUIImage(new Rectangle(-27, -7, 20, 20), new Rectangle(17, 0, 20, 24), statusIcons, Alignment.TopLeft, drowningBar); - healthBar = new GUIProgressBar(new Rectangle(30, GameMain.GraphicsHeight - 230, width, height), Color.Red, 1.0f); + healthBar = new GUIProgressBar(new Rectangle(30, GameMain.GraphicsHeight - 230, width, height), Color.Red, GUI.Style, 1.0f, Alignment.TopLeft); new GUIImage(new Rectangle(-26, -7, 20, 20), new Rectangle(0, 0, 13, 24), statusIcons, Alignment.TopLeft, healthBar); } diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs index 7f94e35ab..0404cb653 100644 --- a/Subsurface/Source/DebugConsole.cs +++ b/Subsurface/Source/DebugConsole.cs @@ -323,7 +323,7 @@ namespace Barotrauma break; case "fixhull": case "fixwalls": - foreach (Structure w in Structure.wallList) + foreach (Structure w in Structure.WallList) { for (int i = 0 ; i < w.SectionCount; i++) { diff --git a/Subsurface/Source/Events/MonsterEvent.cs b/Subsurface/Source/Events/MonsterEvent.cs index abd22b1be..5a7110191 100644 --- a/Subsurface/Source/Events/MonsterEvent.cs +++ b/Subsurface/Source/Events/MonsterEvent.cs @@ -35,7 +35,7 @@ namespace Barotrauma for (int i = 0; i < amount; i++) { - Vector2 position = (randomWayPoint == null) ? Vector2.Zero : FarseerPhysics.ConvertUnits.ToSimUnits(randomWayPoint.Position); + Vector2 position = (randomWayPoint == null) ? Vector2.Zero : randomWayPoint.Position; //!!!!!!!!!!!!!!!!!! if (spawnDeep) diff --git a/Subsurface/Source/Events/Quests/MonsterQuest.cs b/Subsurface/Source/Events/Quests/MonsterQuest.cs index d1e0ab8c6..7693d0a97 100644 --- a/Subsurface/Source/Events/Quests/MonsterQuest.cs +++ b/Subsurface/Source/Events/Quests/MonsterQuest.cs @@ -31,7 +31,7 @@ namespace Barotrauma { Vector2 position = level.PositionsOfInterest[Rand.Int(level.PositionsOfInterest.Count, false)]; - monster = Character.Create(monsterFile, ConvertUnits.ToSimUnits(position)); + monster = Character.Create(monsterFile, position); } public override void Update(float deltaTime) diff --git a/Subsurface/Source/GUI/GUIProgressBar.cs b/Subsurface/Source/GUI/GUIProgressBar.cs index 53e33d6e4..a0b8dfcb1 100644 --- a/Subsurface/Source/GUI/GUIProgressBar.cs +++ b/Subsurface/Source/GUI/GUIProgressBar.cs @@ -37,12 +37,18 @@ namespace Barotrauma } public GUIProgressBar(Rectangle rect, Color color, float barSize, Alignment alignment, GUIComponent parent = null) - : base(null) + : this(rect,color,null, barSize,alignment, parent) + { + + } + + public GUIProgressBar(Rectangle rect, Color color, GUIStyle style, float barSize, Alignment alignment, GUIComponent parent = null) + : base(style) { this.rect = rect; this.color = color; isHorizontal = (rect.Width > rect.Height); - + this.alignment = alignment; margin = 5; @@ -50,19 +56,36 @@ namespace Barotrauma if (parent != null) parent.AddChild(this); - frame = new GUIFrame(new Rectangle(0,0,0,0), Color.White, null, this); + frame = new GUIFrame(new Rectangle(0, 0, 0, 0), Color.Black, null, this); this.barSize = barSize; UpdateRect(); + + if (style != null) style.Apply(this); + } + + public override void ApplyStyle(GUIComponentStyle style) + { + if (frame == null) return; + + frame.Color = style.Color; + frame.HoverColor = style.HoverColor; + frame.SelectedColor = style.SelectedColor; + + Padding = style.Padding; + + frame.OutlineColor = style.OutlineColor; + + this.style = style; } private void UpdateRect() { rect = new Rectangle( - frame.Rect.X + margin, - frame.Rect.Y + margin, - isHorizontal ? (int)((frame.Rect.Width - margin * 2) * barSize) : (frame.Rect.Width - margin * 2), - isHorizontal ? (frame.Rect.Height - margin * 2) : (int)((frame.Rect.Height - margin * 2) * barSize)); + (int)(frame.Rect.X + padding.X), + (int)(frame.Rect.Y + padding.Y), + isHorizontal ? (int)((frame.Rect.Width - padding.X - padding.Z) * barSize) : (frame.Rect.Width - margin * 2), + isHorizontal ? (int)(frame.Rect.Height - padding.Y - padding.W) : (int)((frame.Rect.Height - margin * 2) * barSize)); } public override void Draw(SpriteBatch spriteBatch) diff --git a/Subsurface/Source/GameSession/GameModes/TutorialMode.cs b/Subsurface/Source/GameSession/GameModes/TutorialMode.cs index 2c64e0bfe..0ad102f87 100644 --- a/Subsurface/Source/GameSession/GameModes/TutorialMode.cs +++ b/Subsurface/Source/GameSession/GameModes/TutorialMode.cs @@ -333,7 +333,7 @@ namespace Barotrauma infoBox = CreateInfoFrame("Uh-oh... Something enormous just appeared on the radar."); List windows = new List(); - foreach (Structure s in Structure.wallList) + foreach (Structure s in Structure.WallList) { if (s.CastShadow || !s.HasBody) continue; diff --git a/Subsurface/Source/Items/Components/Door.cs b/Subsurface/Source/Items/Components/Door.cs index 016de1795..d46eff019 100644 --- a/Subsurface/Source/Items/Components/Door.cs +++ b/Subsurface/Source/Items/Components/Door.cs @@ -353,7 +353,7 @@ namespace Barotrauma.Items.Components if (connection.Name=="toggle") { isOpen = !isOpen; - PlaySound(ActionType.OnUse, item.Position); + PlaySound(ActionType.OnUse, item.WorldPosition); } else if (connection.Name == "set_state") { diff --git a/Subsurface/Source/Items/Components/Holdable/Propulsion.cs b/Subsurface/Source/Items/Components/Holdable/Propulsion.cs index 525f9adcc..4455d4638 100644 --- a/Subsurface/Source/Items/Components/Holdable/Propulsion.cs +++ b/Subsurface/Source/Items/Components/Holdable/Propulsion.cs @@ -88,7 +88,7 @@ namespace Barotrauma.Items.Components if (!string.IsNullOrWhiteSpace(particles)) { - GameMain.ParticleManager.CreateParticle(particles, item.Position, + GameMain.ParticleManager.CreateParticle(particles, item.WorldPosition, item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi), 0.0f, item.CurrentHull); } diff --git a/Subsurface/Source/Items/Components/Signal/LightComponent.cs b/Subsurface/Source/Items/Components/Signal/LightComponent.cs index 820063d4a..6ab43eafa 100644 --- a/Subsurface/Source/Items/Components/Signal/LightComponent.cs +++ b/Subsurface/Source/Items/Components/Signal/LightComponent.cs @@ -100,8 +100,10 @@ namespace Barotrauma.Items.Components base.Update(deltaTime, cam); if (item.CurrentHull != null) { - //light.Submarine = item.CurrentHull.Submarine; + light.Submarine = item.CurrentHull.Submarine; } + + if (item.container != null) { diff --git a/Subsurface/Source/Map/Hull.cs b/Subsurface/Source/Map/Hull.cs index 94eb23689..924437757 100644 --- a/Subsurface/Source/Map/Hull.cs +++ b/Subsurface/Source/Map/Hull.cs @@ -479,21 +479,21 @@ namespace Barotrauma } //returns the water block which contains the point (or null if it isn't inside any) - public static Hull FindHull(Vector2 worldPosition, Hull guess = null) + public static Hull FindHull(Vector2 position, Hull guess = null, bool useWorldCoordinates = true) { - return FindHull(worldPosition, hullList, guess); + return FindHull(position, hullList, guess, useWorldCoordinates); } - public static Hull FindHull(Vector2 worldPosition, List hulls, Hull guess = null) + public static Hull FindHull(Vector2 position, List hulls, Hull guess = null, bool useWorldCoordinates = true) { if (guess != null && hulls.Contains(guess)) { - if (Submarine.RectContains(guess.WorldRect, worldPosition)) return guess; + if (Submarine.RectContains(useWorldCoordinates ? guess.WorldRect : guess.rect, position)) return guess; } foreach (Hull hull in hulls) { - if (Submarine.RectContains(hull.WorldRect, worldPosition)) return hull; + if (Submarine.RectContains(useWorldCoordinates ? hull.WorldRect : hull.rect, position)) return hull; } return null; diff --git a/Subsurface/Source/Map/Levels/Level.cs b/Subsurface/Source/Map/Levels/Level.cs index 750bc26d6..e2142f881 100644 --- a/Subsurface/Source/Map/Levels/Level.cs +++ b/Subsurface/Source/Map/Levels/Level.cs @@ -41,7 +41,6 @@ namespace Barotrauma //List bodies; private List cells; - private VertexPositionTexture[] vertices; //private VertexBuffer vertexBuffer; private Vector2 startPosition, endPosition; @@ -314,7 +313,9 @@ namespace Barotrauma startPosition.Y = borders.Height; endPosition.Y = borders.Height; - vertices = GeneratePolygons(cells, pathCells); + renderer.BodyVertices = GeneratePolygons(cells, pathCells); + renderer.WallVertices = GenerateWallShapes(cells); + wrappingWalls = new WrappingWall[2, 2]; @@ -325,7 +326,8 @@ namespace Barotrauma wrappingWalls[side, i] = new WrappingWall(pathCells, cells, borders.Height * 0.5f, (side == 0 ? -1 : 1) * (i == 0 ? 1 : 2)); - wrappingWalls[side, i].Vertices = GeneratePolygons(wrappingWalls[side, i].Cells, new List(), false); + wrappingWalls[side, i].BodyVertices = GeneratePolygons(wrappingWalls[side, i].Cells, new List(), false); + wrappingWalls[side, i].WallVertices = GenerateWallShapes(wrappingWalls[side, i].Cells); //wrappingWalls[side, i].Cells[0].edges[1].isSolid = false; //wrappingWalls[side, i].Cells[0].edges[3].isSolid = false; @@ -622,9 +624,9 @@ namespace Barotrauma } - private VertexPositionTexture[] GeneratePolygons(List cells, List emptyCells, bool setSolid=true) + private VertexPositionColor[] GeneratePolygons(List cells, List emptyCells, bool setSolid=true) { - List verticeList = new List(); + List verticeList = new List(); //bodies = new List(); List tempVertices = new List(); @@ -657,14 +659,14 @@ namespace Barotrauma continue; } - //var triangles = MathUtils.TriangulateConvexHull(tempVertices, cell.Center); - //for (int i = 0; i < triangles.Count; i++) - //{ - // foreach (Vector2 vertex in triangles[i]) - // { - // verticeList.Add(new VertexPositionTexture(new Vector3(vertex, 0.0f), vertex/1000.0f)); - // } - //} + var triangles = MathUtils.TriangulateConvexHull(tempVertices, cell.Center); + for (int i = 0; i < triangles.Count; i++) + { + foreach (Vector2 vertex in triangles[i]) + { + verticeList.Add(new VertexPositionColor(new Vector3(vertex, 0.0f), Color.Black)); + } + } if (bodyPoints.Count < 2) continue; @@ -684,7 +686,7 @@ namespace Barotrauma bodyPoints[i] = ConvertUnits.ToSimUnits(bodyPoints[i]); } - var triangles = MathUtils.TriangulateConvexHull(bodyPoints, cell.Center); + triangles = MathUtils.TriangulateConvexHull(bodyPoints, cell.Center); Body edgeBody = new Body(GameMain.World); @@ -706,15 +708,12 @@ namespace Barotrauma bodies.Add(edgeBody); } - - verticeList = GenerateWallShapes(cells); - return verticeList.ToArray(); } - private List GenerateWallShapes(List cells) + private VertexPositionTexture[] GenerateWallShapes(List cells) { - float wallThickness = 500.0f; + float inwardThickness = 500.0f, outWardThickness = 30.0f; List verticeList = new List(); @@ -726,13 +725,13 @@ namespace Barotrauma if (edge.cell1 != null && edge.cell1.body == null) edge.cell1 = null; if (edge.cell2 != null && edge.cell2.body == null) edge.cell2 = null; - //CompareCCW compare = new CompareCCW(cell.Center); - //if (compare.Compare(edge.point1, edge.point2) == -1) - //{ - // var temp = edge.point1; - // edge.point1 = edge.point2; - // edge.point2 = temp; - //} + CompareCCW compare = new CompareCCW(cell.Center); + if (compare.Compare(edge.point1, edge.point2) == -1) + { + var temp = edge.point1; + edge.point1 = edge.point2; + edge.point2 = temp; + } } } @@ -758,7 +757,7 @@ namespace Barotrauma rightEdge = edge2; } } - + Vector2 leftNormal = Vector2.Zero, rightNormal = Vector2.Zero; if (leftEdge == null) @@ -783,6 +782,10 @@ namespace Barotrauma Vector2.Normalize(GetEdgeNormal(rightEdge) + GetEdgeNormal(edge, cell)) : Vector2.Normalize(rightEdge.Center - edge.point2); } + + + + for (int i = 0; i < 2; i++) { Vector2[] verts = new Vector2[3]; @@ -791,9 +794,9 @@ namespace Barotrauma if (i==0) { - verts[0] = edge.point1; - verts[1] = edge.point2; - verts[2] = edge.point1 + leftNormal * wallThickness; + verts[0] = edge.point1 - leftNormal * outWardThickness; + verts[1] = edge.point2 - rightNormal * outWardThickness; + verts[2] = edge.point1 + leftNormal * inwardThickness; vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], 0.0f), Vector2.Zero); vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], 0.0f), Vector2.UnitX); @@ -801,9 +804,9 @@ namespace Barotrauma } else { - verts[0] = edge.point1 + leftNormal * wallThickness; - verts[1] = edge.point2; - verts[2] = edge.point2 + rightNormal * wallThickness; + verts[0] = edge.point1 + leftNormal * inwardThickness; + verts[1] = edge.point2 - rightNormal * outWardThickness; + verts[2] = edge.point2 + rightNormal * inwardThickness; vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], 0.0f), new Vector2(0.0f, 0.5f)); vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], 0.0f), Vector2.UnitX); @@ -821,7 +824,7 @@ namespace Barotrauma } } - return verticeList; + return verticeList.ToArray(); } private Vector2 GetEdgeNormal(GraphEdge edge, VoronoiCell cell = null) @@ -953,16 +956,21 @@ namespace Barotrauma // } //} - public void Draw(SpriteBatch spriteBatch) + public void Update (float deltaTime) + { + renderer.Update(deltaTime); + } + + public void DrawFront(SpriteBatch spriteBatch) { if (renderer == null) return; renderer.Draw(spriteBatch); } - public void Render(GraphicsDevice graphicsDevice, Camera cam) + public void DrawBack(SpriteBatch spriteBatch, Camera cam, BackgroundSpriteManager backgroundSpriteManager = null) { if (renderer == null) return; - renderer.Render(graphicsDevice, cam, vertices); + renderer.DrawBackground(spriteBatch, cam, backgroundSpriteManager); } @@ -1094,9 +1102,7 @@ namespace Barotrauma private void Unload() { renderer = null; - - vertices = null; - + cells = null; bodies.Clear(); diff --git a/Subsurface/Source/Map/Levels/LevelRenderer.cs b/Subsurface/Source/Map/Levels/LevelRenderer.cs index 6ff978245..6ed2b1640 100644 --- a/Subsurface/Source/Map/Levels/LevelRenderer.cs +++ b/Subsurface/Source/Map/Levels/LevelRenderer.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; @@ -9,20 +10,32 @@ namespace Barotrauma { class LevelRenderer { - private static BasicEffect basicEffect; + private static Sprite background, backgroundTop; + private static Texture2D dustParticles; private static Texture2D shaftTexture; - private Level level; + Vector2 dustOffset; + private Level level; + + public VertexPositionTexture[] WallVertices; + public VertexPositionColor[] BodyVertices; + public LevelRenderer(Level level) { if (shaftTexture == null) shaftTexture = TextureLoader.FromFile("Content/Map/shaft.png"); + if (background==null) + { + background = new Sprite("Content/Map/background.png", Vector2.Zero); + backgroundTop = new Sprite("Content/Map/background2.png", Vector2.Zero); + dustParticles = Sprite.LoadTexture("Content/Map/dustparticles.png"); + } + if (basicEffect == null) { - basicEffect = new BasicEffect(GameMain.CurrGraphicsDevice); basicEffect.VertexColorEnabled = false; @@ -33,6 +46,75 @@ namespace Barotrauma this.level = level; } + public void Update(float deltaTime) + { + + dustOffset -= Vector2.UnitY * 10.0f * (float)deltaTime; + } + + public void DrawBackground(SpriteBatch spriteBatch, Camera cam, BackgroundSpriteManager backgroundSpriteManager = null) + { + spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearWrap); + + Vector2 backgroundPos = cam.Position; + //if (Level.Loaded != null) backgroundPos -= Level.Loaded.Position; + backgroundPos.Y = -backgroundPos.Y; + backgroundPos /= 20.0f; + + if (backgroundPos.Y < 1024) + { + if (backgroundPos.Y > -1024) + { + background.SourceRect = new Rectangle((int)backgroundPos.X, (int)Math.Max(backgroundPos.Y, 0), 1024, 1024); + background.DrawTiled(spriteBatch, + (backgroundPos.Y < 0) ? new Vector2(0.0f, -backgroundPos.Y) : Vector2.Zero, + new Vector2(GameMain.GraphicsWidth, 1024 - backgroundPos.Y), + Vector2.Zero, Color.White); + } + + if (backgroundPos.Y < 0) + { + backgroundTop.SourceRect = new Rectangle((int)backgroundPos.X, (int)backgroundPos.Y, 1024, (int)Math.Min(-backgroundPos.Y, 1024)); + backgroundTop.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, Math.Min(-backgroundPos.Y, GameMain.GraphicsHeight)), + Vector2.Zero, Color.White); + } + } + + spriteBatch.End(); + + spriteBatch.Begin(SpriteSortMode.BackToFront, + BlendState.AlphaBlend, + SamplerState.LinearWrap, DepthStencilState.Default, null, null, + cam.Transform); + + if (backgroundSpriteManager!=null) backgroundSpriteManager.Draw(spriteBatch); + + spriteBatch.End(); + + spriteBatch.Begin(SpriteSortMode.BackToFront, + BlendState.AlphaBlend, + SamplerState.LinearWrap); + + backgroundPos = new Vector2(cam.WorldView.X, cam.WorldView.Y) + dustOffset; + //if (Level.Loaded != null) backgroundPos -= Level.Loaded.Position; + + Rectangle viewRect = cam.WorldView; + viewRect.Y = -viewRect.Y; + + float multiplier = 0.8f; + for (int i = 1; i < 5; i++) + { + spriteBatch.Draw(dustParticles, new Rectangle(0,0,GameMain.GraphicsWidth,GameMain.GraphicsHeight), + new Rectangle((int)((backgroundPos.X * multiplier)), (int)((-backgroundPos.Y * multiplier)), cam.WorldView.Width*2, cam.WorldView.Height*2), + Color.White * multiplier, 0.0f, Vector2.Zero, SpriteEffects.None, 1.0f - multiplier); + multiplier -= 0.1f; + } + + spriteBatch.End(); + + RenderWalls(GameMain.CurrGraphicsDevice, cam); + } + public void Draw(SpriteBatch spriteBatch) { Vector2 pos = new Vector2(0.0f, -level.StartPosition.Y);// level.EndPosition; @@ -54,36 +136,50 @@ namespace Barotrauma } - public void Render(GraphicsDevice graphicsDevice, Camera cam, VertexPositionTexture[] vertices) + public void RenderWalls(GraphicsDevice graphicsDevice, Camera cam) { - if (vertices == null) return; - if (vertices.Length <= 0) return; + if (WallVertices == null || WallVertices.Length <= 0) return; basicEffect.World = cam.ShaderTransform * Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f; - basicEffect.CurrentTechnique.Passes[0].Apply(); - graphicsDevice.SamplerStates[0] = SamplerState.LinearWrap; - graphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, vertices, 0, (int)Math.Floor(vertices.Length / 3.0f)); + basicEffect.VertexColorEnabled = true; + basicEffect.TextureEnabled = false; + basicEffect.CurrentTechnique = basicEffect.Techniques["BasicEffect_VertexColor"]; + basicEffect.CurrentTechnique.Passes[0].Apply(); + graphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, BodyVertices, 0, (int)Math.Floor(BodyVertices.Length / 3.0f)); for (int side = 0; side < 2; side++) { for (int i = 0; i < 2; i++) { - // basicEffect.World = Matrix.CreateTranslation( - // new Vector3(-Submarine.Loaded.Position + level.WrappingWalls[side, i].Offset, 0.0f)) * - // cam.ShaderTransform * - // Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f; - - // basicEffect.CurrentTechnique.Passes[0].Apply(); - graphicsDevice.DrawUserPrimitives( - PrimitiveType.TriangleList, - level.WrappingWalls[side, i].Vertices, 0, - (int)Math.Floor(level.WrappingWalls[side, i].Vertices.Length / 3.0f)); + PrimitiveType.TriangleList, level.WrappingWalls[side, i].BodyVertices, 0, + (int)Math.Floor(level.WrappingWalls[side, i].BodyVertices.Length / 3.0f)); + + } + } + + basicEffect.VertexColorEnabled = false; + basicEffect.TextureEnabled = true; + basicEffect.CurrentTechnique = basicEffect.Techniques["BasicEffect_Texture"]; + basicEffect.CurrentTechnique.Passes[0].Apply(); + graphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, WallVertices, 0, (int)Math.Floor(WallVertices.Length / 3.0f)); + + for (int side = 0; side < 2; side++) + { + for (int i = 0; i < 2; i++) + { + basicEffect.VertexColorEnabled = false; + basicEffect.TextureEnabled = true; + basicEffect.CurrentTechnique = basicEffect.Techniques["BasicEffect_Texture"]; + basicEffect.CurrentTechnique.Passes[0].Apply(); + graphicsDevice.DrawUserPrimitives( + PrimitiveType.TriangleList, level.WrappingWalls[side, i].WallVertices, 0, + (int)Math.Floor(level.WrappingWalls[side, i].WallVertices.Length / 3.0f)); } } diff --git a/Subsurface/Source/Map/Levels/WrappingWall.cs b/Subsurface/Source/Map/Levels/WrappingWall.cs index 21a5b5a2c..5a8db2df9 100644 --- a/Subsurface/Source/Map/Levels/WrappingWall.cs +++ b/Subsurface/Source/Map/Levels/WrappingWall.cs @@ -15,7 +15,9 @@ namespace Barotrauma public const float WallWidth = 20000.0f; - public VertexPositionTexture[] Vertices; + public VertexPositionTexture[] WallVertices; + + public VertexPositionColor[] BodyVertices; private Vector2 midPos; private int slot; diff --git a/Subsurface/Source/Map/Lights/ConvexHull.cs b/Subsurface/Source/Map/Lights/ConvexHull.cs index 404b97d99..fe5db85c5 100644 --- a/Subsurface/Source/Map/Lights/ConvexHull.cs +++ b/Subsurface/Source/Map/Lights/ConvexHull.cs @@ -310,10 +310,10 @@ namespace Barotrauma.Lights { Vector3 offset = Vector3.Zero; - if (parentEntity != null && parentEntity.Submarine != null) - { - offset = new Vector3(parentEntity.Submarine.DrawPosition.X, parentEntity.Submarine.DrawPosition.Y, 0.0f); - } + if (parentEntity != null && parentEntity.Submarine != null) + { + offset = new Vector3(parentEntity.Submarine.DrawPosition.X, parentEntity.Submarine.DrawPosition.Y, 0.0f); + } shadowEffect.World = Matrix.CreateTranslation(offset) * transform; diff --git a/Subsurface/Source/Map/LocationType.cs b/Subsurface/Source/Map/LocationType.cs index a75c36dc0..cbf510651 100644 --- a/Subsurface/Source/Map/LocationType.cs +++ b/Subsurface/Source/Map/LocationType.cs @@ -107,10 +107,15 @@ namespace Barotrauma return null; } - public static LocationType Random() + public static LocationType Random(string seed = "") { Debug.Assert(list.Count > 0, "LocationType.list.Count == 0, you probably need to initialize LocationTypes"); + if (!string.IsNullOrWhiteSpace(seed)) + { + Rand.SetSyncedSeed(ToolBox.StringToInt(seed)); + } + int randInt = Rand.Int(totalWeight, false); foreach (LocationType type in list) diff --git a/Subsurface/Source/Map/Structure.cs b/Subsurface/Source/Map/Structure.cs index c31e1168e..7f60d88e2 100644 --- a/Subsurface/Source/Map/Structure.cs +++ b/Subsurface/Source/Map/Structure.cs @@ -41,7 +41,7 @@ namespace Barotrauma class Structure : MapEntity, IDamageable { public static int wallSectionSize = 100; - public static List wallList = new List(); + public static List WallList = new List(); ConvexHull convexHull; @@ -169,7 +169,7 @@ namespace Barotrauma bodies.Add(newBody); - wallList.Add(this); + WallList.Add(this); int xsections = 1; int ysections = 1; @@ -273,7 +273,7 @@ namespace Barotrauma { base.Remove(); - if (wallList.Contains(this)) wallList.Remove(this); + if (WallList.Contains(this)) WallList.Remove(this); if (bodies != null) { diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index e7371907f..b8d17dce4 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -354,34 +354,7 @@ namespace Barotrauma lastPickedFraction = closestFraction; return closestBody; } - - //public static Body PickBody(Vector2 point) - //{ - // Body foundBody = null; - // AABB aabb = new AABB(point, point); - - // GameMain.World.QueryAABB(p => - // { - // foundBody = p.Body; - - // return true; - - // }, ref aabb); - - // return foundBody; - //} - - //public static bool InsideWall(Vector2 point) - //{ - // Body foundBody = PickBody(point); - // if (foundBody==null) return false; - - // Structure wall = foundBody.UserData as Structure; - // if (wall == null || wall.IsPlatform) return false; - - // return true; - //} - + //movement ---------------------------------------------------- diff --git a/Subsurface/Source/Map/SubmarineBody.cs b/Subsurface/Source/Map/SubmarineBody.cs index 79aa09b8c..7bf92e0a9 100644 --- a/Subsurface/Source/Map/SubmarineBody.cs +++ b/Subsurface/Source/Map/SubmarineBody.cs @@ -108,13 +108,17 @@ namespace Barotrauma (int)ConvertUnits.ToDisplayUnits(hullAABB.UpperBound.Y), (int)ConvertUnits.ToDisplayUnits(hullAABB.Extents.X * 2.0f), (int)ConvertUnits.ToDisplayUnits(hullAABB.Extents.Y * 2.0f)); + + //var triangulatedVertices = Triangulate.ConvexPartition(shapevertices, TriangulationAlgorithm.Bayazit); + body = BodyFactory.CreateBody(GameMain.World, this); - var triangulatedVertices = Triangulate.ConvexPartition(shapevertices, TriangulationAlgorithm.Bayazit); + foreach (Hull hull in Hull.hullList) + { + FixtureFactory.AttachRectangle(ConvertUnits.ToSimUnits(hull.Rect.Width), ConvertUnits.ToSimUnits(hull.Rect.Height), 5.0f, hull.SimPosition, body, this); + } - body = BodyFactory.CreateCompoundPolygon(GameMain.World, triangulatedVertices, 5.0f); body.BodyType = BodyType.Dynamic; - body.CollisionCategories = Physics.CollisionMisc | Physics.CollisionWall; body.CollidesWith = Physics.CollisionLevel | Physics.CollisionCharacter; body.Restitution = Restitution; @@ -125,13 +129,13 @@ namespace Barotrauma body.SleepingAllowed = false; body.IgnoreGravity = true; body.OnCollision += OnCollision; - body.UserData = this; + //body.UserData = this; } private List GenerateConvexHull() { - if (!Structure.wallList.Any()) + if (!Structure.WallList.Any()) { return new List() { new Vector2(-1.0f, 1.0f), new Vector2(1.0f, 1.0f), new Vector2(0.0f, -1.0f) }; } @@ -140,7 +144,7 @@ namespace Barotrauma Vector2 leftMost = Vector2.Zero; - foreach (Structure wall in Structure.wallList) + foreach (Structure wall in Structure.WallList) { for (int x = -1; x <= 1; x += 2) { @@ -175,7 +179,7 @@ namespace Barotrauma endPoint = points[i]; } } - + currPoint = endPoint; } @@ -184,9 +188,6 @@ namespace Barotrauma return hullPoints; } - - float collisionRigidness = 1.0f; - public void Update(float deltaTime) { if (Position!=Vector2.Zero) diff --git a/Subsurface/Source/Map/WayPoint.cs b/Subsurface/Source/Map/WayPoint.cs index adab499a0..3477a6a89 100644 --- a/Subsurface/Source/Map/WayPoint.cs +++ b/Subsurface/Source/Map/WayPoint.cs @@ -219,6 +219,12 @@ namespace Barotrauma public static void GenerateSubWaypoints() { + List existingWaypoints = WayPointList.FindAll(wp => wp.spawnType == SpawnType.Path); + foreach (WayPoint wayPoint in existingWaypoints) + { + wayPoint.Remove(); + } + float minDist = 200.0f; float heightFromFloor = 100.0f; diff --git a/Subsurface/Source/Screens/EditMapScreen.cs b/Subsurface/Source/Screens/EditMapScreen.cs index c55633494..4052cdabf 100644 --- a/Subsurface/Source/Screens/EditMapScreen.cs +++ b/Subsurface/Source/Screens/EditMapScreen.cs @@ -134,6 +134,8 @@ namespace Barotrauma GUIComponent.MouseOn = null; characterMode = false; + + if (Submarine.Loaded != null) cam.Position = Submarine.Loaded.Position + Submarine.HiddenSubPosition; //CreateDummyCharacter(); } diff --git a/Subsurface/Source/Screens/GameScreen.cs b/Subsurface/Source/Screens/GameScreen.cs index ed662959f..1e8195cf7 100644 --- a/Subsurface/Source/Screens/GameScreen.cs +++ b/Subsurface/Source/Screens/GameScreen.cs @@ -15,11 +15,6 @@ namespace Barotrauma readonly RenderTarget2D renderTargetWater; readonly RenderTarget2D renderTargetAir; - readonly Sprite background, backgroundTop; - readonly Texture2D dustParticles; - - Vector2 dustOffset; - public BackgroundSpriteManager BackgroundSpriteManager; public Camera Cam @@ -36,9 +31,6 @@ namespace Barotrauma renderTargetWater = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight); renderTargetAir = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight); - background = new Sprite("Content/Map/background.png", Vector2.Zero); - backgroundTop = new Sprite("Content/Map/background2.png", Vector2.Zero); - dustParticles = Sprite.LoadTexture("Content/Map/dustparticles.png"); BackgroundSpriteManager = new BackgroundSpriteManager("Content/BackgroundSprites/BackgroundSpritePrefabs.xml"); } @@ -83,11 +75,12 @@ namespace Barotrauma GameMain.GameSession.Submarine.ApplyForce(targetMovement * 1000000.0f); } #endif - dustOffset -= Vector2.UnitY * 10.0f * (float)deltaTime; if (GameMain.GameSession!=null) GameMain.GameSession.Update((float)deltaTime); //EventManager.Update(gameTime); + if (Level.Loaded != null) Level.Loaded.Update((float)deltaTime); + Character.UpdateAll(cam, (float)deltaTime); BackgroundSpriteManager.Update(cam, (float)deltaTime); @@ -101,7 +94,11 @@ namespace Barotrauma while (Physics.accumulator >= Physics.step) { cam.MoveCamera((float)Physics.step); - if (Character.Controlled != null) cam.TargetPos = Character.Controlled.WorldPosition; + if (Character.Controlled != null) + { + cam.TargetPos = Character.Controlled.WorldPosition; + Lights.LightManager.ViewPos = Character.Controlled.WorldPosition; + } if (Submarine.Loaded != null) Submarine.Loaded.SetPrevTransform(Submarine.Loaded.Position); @@ -175,6 +172,7 @@ namespace Barotrauma GameMain.LightManager.UpdateObstructVision(graphics, spriteBatch, cam, Character.Controlled==null ? LightManager.ViewPos : Character.Controlled.CursorWorldPosition); + //---------------------------------------------------------------------------------------- //1. draw the background, characters and the parts of the submarine that are behind them //---------------------------------------------------------------------------------------- @@ -182,63 +180,8 @@ namespace Barotrauma graphics.SetRenderTarget(renderTarget); graphics.Clear(new Color(11, 18, 26, 255)); - spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearWrap); + if (Level.Loaded != null) Level.Loaded.DrawBack(spriteBatch, cam, BackgroundSpriteManager); - Vector2 backgroundPos = cam.Position; - //if (Level.Loaded != null) backgroundPos -= Level.Loaded.Position; - backgroundPos.Y = -backgroundPos.Y; - backgroundPos /= 20.0f; - - if (backgroundPos.Y < 1024) - { - if (backgroundPos.Y > -1024) - { - background.SourceRect = new Rectangle((int)backgroundPos.X, (int)Math.Max(backgroundPos.Y, 0), 1024, 1024); - background.DrawTiled(spriteBatch, - (backgroundPos.Y < 0) ? new Vector2(0.0f, -backgroundPos.Y) : Vector2.Zero, - new Vector2(GameMain.GraphicsWidth, 1024 - backgroundPos.Y), - Vector2.Zero, Color.White); - } - - if (backgroundPos.Y < 0) - { - backgroundTop.SourceRect = new Rectangle((int)backgroundPos.X, (int)backgroundPos.Y, 1024, (int)Math.Min(-backgroundPos.Y, 1024)); - backgroundTop.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, Math.Min(-backgroundPos.Y, GameMain.GraphicsHeight)), - Vector2.Zero, Color.White); - } - } - - spriteBatch.End(); - - spriteBatch.Begin(SpriteSortMode.BackToFront, - BlendState.AlphaBlend, - SamplerState.LinearWrap, DepthStencilState.Default, null, null, - cam.Transform); - - BackgroundSpriteManager.Draw(spriteBatch); - - backgroundPos = new Vector2(cam.WorldView.X, cam.WorldView.Y) + dustOffset; - //if (Level.Loaded != null) backgroundPos -= Level.Loaded.Position; - - Rectangle viewRect = cam.WorldView; - viewRect.Y = -viewRect.Y; - - float multiplier = 0.8f; - for (int i = 1; i < 4; i++) - { - spriteBatch.Draw(dustParticles, viewRect, - new Rectangle((int)((backgroundPos.X * multiplier)), (int)((-backgroundPos.Y * multiplier)), cam.WorldView.Width, cam.WorldView.Height), - Color.White * multiplier, 0.0f, Vector2.Zero, SpriteEffects.None, 1.0f-multiplier); - multiplier -= 0.15f; - } - - spriteBatch.End(); - - if (GameMain.GameSession != null && GameMain.GameSession.Level != null) - { - GameMain.GameSession.Level.Render(graphics, cam); - //GameMain.GameSession.Level.SetObserverPosition(cam.WorldViewCenter); - } spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, @@ -344,7 +287,7 @@ namespace Barotrauma Submarine.DrawFront(spriteBatch); - if (Level.Loaded!=null) Level.Loaded.Draw(spriteBatch); + if (Level.Loaded!=null) Level.Loaded.DrawFront(spriteBatch); spriteBatch.End(); diff --git a/Subsurface/Source/Screens/LobbyScreen.cs b/Subsurface/Source/Screens/LobbyScreen.cs index aed41e4ae..5393f7f3d 100644 --- a/Subsurface/Source/Screens/LobbyScreen.cs +++ b/Subsurface/Source/Screens/LobbyScreen.cs @@ -368,8 +368,7 @@ namespace Barotrauma Sprite backGround = GameMain.GameSession.Map.CurrentLocation.Type.Background; spriteBatch.Draw(backGround.Texture, Vector2.Zero, null, Color.White, 0.0f, Vector2.Zero, Math.Max((float)GameMain.GraphicsWidth / backGround.SourceRect.Width, (float)GameMain.GraphicsHeight / backGround.SourceRect.Height), SpriteEffects.None, 0.0f); - - + topPanel.Draw(spriteBatch); bottomPanel[selectedRightPanel].Draw(spriteBatch); diff --git a/Subsurface/Source/Screens/NetLobbyScreen.cs b/Subsurface/Source/Screens/NetLobbyScreen.cs index 065732e91..6d8ca83df 100644 --- a/Subsurface/Source/Screens/NetLobbyScreen.cs +++ b/Subsurface/Source/Screens/NetLobbyScreen.cs @@ -36,6 +36,8 @@ namespace Barotrauma public bool IsServer; public string ServerName, ServerMessage; + private Sprite backgroundSprite; + private GUITextBox serverMessage; public GUIListBox SubList @@ -98,6 +100,9 @@ namespace Barotrauma } private set { + if (levelSeed == value) return; + backgroundSprite = LocationType.Random(LevelSeed).Background; + levelSeed = value; seedBox.Text = levelSeed; } @@ -266,6 +271,7 @@ namespace Barotrauma serverMessage.Wrap = true; serverMessage.TextGetter = GetServerMessage; serverMessage.OnTextChanged = UpdateServerMessage; + } public override void Deselect() @@ -284,7 +290,7 @@ namespace Barotrauma textBox.Select(); Character.Controlled = null; - GameMain.GameScreen.Cam.TargetPos = Vector2.Zero; + //GameMain.GameScreen.Cam.TargetPos = Vector2.Zero; subList.Enabled = GameMain.Server != null || GameMain.NetworkMember.Voting.AllowSubVoting; playerList.Enabled = GameMain.Server != null; @@ -597,19 +603,19 @@ namespace Barotrauma { base.Update(deltaTime); - Vector2 pos = new Vector2( - Submarine.Borders.X + Submarine.Borders.Width / 2, - Submarine.Borders.Y - Submarine.Borders.Height / 2); + //Vector2 pos = new Vector2( + // Submarine.Borders.X + Submarine.Borders.Width / 2, + // Submarine.Borders.Y - Submarine.Borders.Height / 2); - camAngle += (float)deltaTime / 10.0f; - Vector2 offset = (new Vector2( - (float)Math.Cos(camAngle) * (Submarine.Borders.Width / 2.0f), - (float)Math.Sin(camAngle) * (Submarine.Borders.Height / 2.0f))); + //camAngle += (float)deltaTime / 10.0f; + //Vector2 offset = (new Vector2( + // (float)Math.Cos(camAngle) * (Submarine.Borders.Width / 2.0f), + // (float)Math.Sin(camAngle) * (Submarine.Borders.Height / 2.0f))); - pos += offset * 0.8f; + //pos += offset * 0.8f; - GameMain.GameScreen.Cam.TargetPos = pos; - GameMain.GameScreen.Cam.MoveCamera((float)deltaTime); + //GameMain.GameScreen.Cam.TargetPos = pos; + //GameMain.GameScreen.Cam.MoveCamera((float)deltaTime); menu.Update((float)deltaTime); @@ -632,12 +638,17 @@ namespace Barotrauma public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch) { - graphics.Clear(Color.CornflowerBlue); - - GameMain.GameScreen.DrawMap(graphics, spriteBatch); - + graphics.Clear(Color.Black); + spriteBatch.Begin(); + if (backgroundSprite!=null) + { + spriteBatch.Draw(backgroundSprite.Texture, Vector2.Zero, null, Color.White, 0.0f, Vector2.Zero, + Math.Max((float)GameMain.GraphicsWidth / backgroundSprite.SourceRect.Width, (float)GameMain.GraphicsHeight / backgroundSprite.SourceRect.Height), + SpriteEffects.None, 0.0f); + } + menu.Draw(spriteBatch); if (jobInfoFrame != null) jobInfoFrame.Draw(spriteBatch); diff --git a/Subsurface/Source/Screens/ServerListScreen.cs b/Subsurface/Source/Screens/ServerListScreen.cs index 16b7b5543..e3acdaddc 100644 --- a/Subsurface/Source/Screens/ServerListScreen.cs +++ b/Subsurface/Source/Screens/ServerListScreen.cs @@ -81,7 +81,6 @@ namespace Barotrauma GUIButton button = new GUIButton(new Rectangle(-20, -20, 100, 30), "Back", Alignment.TopLeft, GUI.Style, menu); button.OnClicked = GameMain.MainMenuScreen.SelectTab; - button.CanBeSelected = false; button.SelectedColor = button.Color; refreshDisableTimer = DateTime.Now; diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index b1453c56c0baf09072d1b5decdba21df79f00ea3..6e06c07fafb1cdcf8f8e03d3341a424e43e8add4 100644 GIT binary patch delta 14508 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