Пример #1
0
        /// <summary>
        /// Moves away any character that is inside the bounding box of the sub (but not inside the sub)
        /// </summary>
        /// <param name="subTranslation">The translation that was applied to the sub before doing the displacement
        /// (used for determining where to push the characters)</param>
        private void DisplaceCharacters(Vector2 subTranslation)
        {
            Rectangle worldBorders = Borders;

            worldBorders.Location += MathUtils.ToPoint(ConvertUnits.ToDisplayUnits(Body.SimPosition));

            Vector2 translateDir = Vector2.Normalize(subTranslation);

            if (!MathUtils.IsValid(translateDir))
            {
                translateDir = Vector2.UnitY;
            }

            foreach (Character c in Character.CharacterList)
            {
                if (c.AnimController.CurrentHull != null && c.AnimController.CanEnterSubmarine)
                {
                    continue;
                }

                foreach (Limb limb in c.AnimController.Limbs)
                {
                    if (limb.IsSevered)
                    {
                        continue;
                    }
                    //if the character isn't inside the bounding box, continue
                    if (!Submarine.RectContains(worldBorders, limb.WorldPosition))
                    {
                        continue;
                    }

                    //cast a line from the position of the character to the same direction as the translation of the sub
                    //and see where it intersects with the bounding box
                    if (!MathUtils.GetLineRectangleIntersection(limb.WorldPosition,
                                                                limb.WorldPosition + translateDir * 100000.0f, worldBorders, out Vector2 intersection))
                    {
                        //should never happen when casting a line out from inside the bounding box
                        Debug.Assert(false);
                        continue;
                    }


                    //"+ translatedir" in order to move the character slightly away from the wall
                    c.AnimController.SetPosition(ConvertUnits.ToSimUnits(c.WorldPosition + (intersection - limb.WorldPosition)) + translateDir);

                    return;
                }
            }
        }
Пример #2
0
        public void Draw(SpriteBatch spriteBatch, GUICustomComponent mapContainer)
        {
            Rectangle rect = mapContainer.Rect;

            Vector2 viewSize   = new Vector2(rect.Width / zoom, rect.Height / zoom);
            float   edgeBuffer = size * (BackgroundScale - 1.0f) / 2;

            drawOffset.X = MathHelper.Clamp(drawOffset.X, -size - edgeBuffer + viewSize.X / 2.0f, edgeBuffer - viewSize.X / 2.0f);
            drawOffset.Y = MathHelper.Clamp(drawOffset.Y, -size - edgeBuffer + viewSize.Y / 2.0f, edgeBuffer - viewSize.Y / 2.0f);

            drawOffsetNoise = new Vector2(
                (float)PerlinNoise.CalculatePerlin(Timing.TotalTime * 0.1f % 255, Timing.TotalTime * 0.1f % 255, 0) - 0.5f,
                (float)PerlinNoise.CalculatePerlin(Timing.TotalTime * 0.2f % 255, Timing.TotalTime * 0.2f % 255, 0.5f) - 0.5f) * 10.0f;

            Vector2 viewOffset = drawOffset + drawOffsetNoise;

            Vector2 rectCenter = new Vector2(rect.Center.X, rect.Center.Y);

            Rectangle prevScissorRect = GameMain.Instance.GraphicsDevice.ScissorRectangle;

            spriteBatch.End();
            spriteBatch.GraphicsDevice.ScissorRectangle = Rectangle.Intersect(prevScissorRect, rect);
            spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);

            for (int x = 0; x < mapTiles.GetLength(0); x++)
            {
                for (int y = 0; y < mapTiles.GetLength(1); y++)
                {
                    Vector2 mapPos = new Vector2(
                        x * generationParams.TileSpriteSpacing.X + ((y % 2 == 0) ? 0.0f : generationParams.TileSpriteSpacing.X * 0.5f),
                        y * generationParams.TileSpriteSpacing.Y);

                    mapPos.X -= size / 2 * (BackgroundScale - 1.0f);
                    mapPos.Y -= size / 2 * (BackgroundScale - 1.0f);

                    Vector2 scale = new Vector2(
                        generationParams.TileSpriteSize.X / mapTiles[x, y].Sprite.size.X,
                        generationParams.TileSpriteSize.Y / mapTiles[x, y].Sprite.size.Y);
                    mapTiles[x, y].Sprite.Draw(spriteBatch, rectCenter + (mapPos + viewOffset) * zoom, Color.White,
                                               origin: new Vector2(256.0f, 256.0f), rotate: 0, scale: scale * zoom, spriteEffect: mapTiles[x, y].SpriteEffect);
                }
            }
#if DEBUG
            if (generationParams.ShowNoiseMap)
            {
                GUI.DrawRectangle(spriteBatch, rectCenter + (borders.Location.ToVector2() + viewOffset) * zoom, borders.Size.ToVector2() * zoom, Color.White, true);
            }
#endif
            Vector2 topLeft = rectCenter + viewOffset * zoom;
            topLeft.X = (int)topLeft.X;
            topLeft.Y = (int)topLeft.Y;

            Vector2 bottomRight = rectCenter + (viewOffset + new Vector2(size, size)) * zoom;
            bottomRight.X = (int)bottomRight.X;
            bottomRight.Y = (int)bottomRight.Y;

            spriteBatch.Draw(noiseTexture,
                             destinationRectangle: new Rectangle((int)topLeft.X, (int)topLeft.Y, (int)(bottomRight.X - topLeft.X), (int)(bottomRight.Y - topLeft.Y)),
                             sourceRectangle: null,
                             color: Color.White);

            if (topLeft.X > rect.X)
            {
                GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Y, (int)(topLeft.X - rect.X), rect.Height), Color.Black * 0.8f, true);
            }
            if (topLeft.Y > rect.Y)
            {
                GUI.DrawRectangle(spriteBatch, new Rectangle((int)topLeft.X, rect.Y, (int)(bottomRight.X - topLeft.X), (int)(topLeft.Y - rect.Y)), Color.Black * 0.8f, true);
            }
            if (bottomRight.X < rect.Right)
            {
                GUI.DrawRectangle(spriteBatch, new Rectangle((int)bottomRight.X, rect.Y, (int)(rect.Right - bottomRight.X), rect.Height), Color.Black * 0.8f, true);
            }
            if (bottomRight.Y < rect.Bottom)
            {
                GUI.DrawRectangle(spriteBatch, new Rectangle((int)topLeft.X, (int)bottomRight.Y, (int)(bottomRight.X - topLeft.X), (int)(rect.Bottom - bottomRight.Y)), Color.Black * 0.8f, true);
            }

            var   sourceRect    = rect;
            float rawNoiseScale = 1.0f + Noise[(int)(Timing.TotalTime * 100 % Noise.GetLength(0) - 1), (int)(Timing.TotalTime * 100 % Noise.GetLength(1) - 1)];
            cameraNoiseStrength = Noise[(int)(Timing.TotalTime * 10 % Noise.GetLength(0) - 1), (int)(Timing.TotalTime * 10 % Noise.GetLength(1) - 1)];

            rawNoiseSprite.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(),
                                     startOffset: new Point(Rand.Range(0, rawNoiseSprite.SourceRect.Width), Rand.Range(0, rawNoiseSprite.SourceRect.Height)),
                                     color: Color.White * cameraNoiseStrength * 0.5f,
                                     textureScale: Vector2.One * rawNoiseScale);

            rawNoiseSprite.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(),
                                     startOffset: new Point(Rand.Range(0, rawNoiseSprite.SourceRect.Width), Rand.Range(0, rawNoiseSprite.SourceRect.Height)),
                                     color: new Color(20, 20, 20, 100),
                                     textureScale: Vector2.One * rawNoiseScale * 2);

            if (generationParams.ShowLocations)
            {
                foreach (LocationConnection connection in connections)
                {
                    Color connectionColor;
                    if (GameMain.DebugDraw)
                    {
                        float sizeFactor = MathUtils.InverseLerp(
                            MapGenerationParams.Instance.SmallLevelConnectionLength,
                            MapGenerationParams.Instance.LargeLevelConnectionLength,
                            connection.Length);

                        connectionColor = ToolBox.GradientLerp(sizeFactor, Color.LightGreen, Color.Orange, Color.Red);
                    }
                    else
                    {
                        connectionColor = ToolBox.GradientLerp(connection.Difficulty / 100.0f,
                                                               MapGenerationParams.Instance.LowDifficultyColor,
                                                               MapGenerationParams.Instance.MediumDifficultyColor,
                                                               MapGenerationParams.Instance.HighDifficultyColor);
                    }

                    int width = (int)(3 * zoom);

                    if (SelectedLocation != CurrentLocation &&
                        (connection.Locations.Contains(SelectedLocation) && connection.Locations.Contains(CurrentLocation)))
                    {
                        connectionColor = Color.Gold;
                        width          *= 2;
                    }
                    else if (highlightedLocation != CurrentLocation &&
                             (connection.Locations.Contains(highlightedLocation) && connection.Locations.Contains(CurrentLocation)))
                    {
                        connectionColor = Color.Lerp(connectionColor, Color.White, 0.5f);
                        width          *= 2;
                    }
                    else if (!connection.Passed)
                    {
                        //crackColor *= 0.5f;
                    }

                    for (int i = 0; i < connection.CrackSegments.Count; i++)
                    {
                        var segment = connection.CrackSegments[i];

                        Vector2 start = rectCenter + (segment[0] + viewOffset) * zoom;
                        Vector2 end   = rectCenter + (segment[1] + viewOffset) * zoom;

                        if (!rect.Contains(start) && !rect.Contains(end))
                        {
                            continue;
                        }
                        else
                        {
                            if (MathUtils.GetLineRectangleIntersection(start, end, new Rectangle(rect.X, rect.Y + rect.Height, rect.Width, rect.Height), out Vector2 intersection))
                            {
                                if (!rect.Contains(start))
                                {
                                    start = intersection;
                                }
                                else
                                {
                                    end = intersection;
                                }
                            }
                        }

                        float distFromPlayer = Vector2.Distance(CurrentLocation.MapPosition, (segment[0] + segment[1]) / 2.0f);
                        float dist           = Vector2.Distance(start, end);

                        float a = GameMain.DebugDraw ? 1.0f : (200.0f - distFromPlayer) / 200.0f;
                        spriteBatch.Draw(generationParams.ConnectionSprite.Texture,
                                         new Rectangle((int)start.X, (int)start.Y, (int)(dist - 1 * zoom), width),
                                         null, connectionColor * MathHelper.Clamp(a, 0.1f, 0.5f), MathUtils.VectorToAngle(end - start),
                                         new Vector2(0, 16), SpriteEffects.None, 0.01f);
                    }

                    if (GameMain.DebugDraw && zoom > 1.0f && generationParams.ShowLevelTypeNames)
                    {
                        Vector2 center = rectCenter + (connection.CenterPos + viewOffset) * zoom;
                        if (rect.Contains(center))
                        {
                            GUI.DrawString(spriteBatch, center, connection.Biome.Name + " (" + connection.Difficulty + ")", Color.White);
                        }
                    }
                }

                rect.Inflate(8, 8);
                GUI.DrawRectangle(spriteBatch, rect, Color.Black, false, 0.0f, 8);
                GUI.DrawRectangle(spriteBatch, rect, Color.LightGray);

                for (int i = 0; i < Locations.Count; i++)
                {
                    Location location = Locations[i];
                    Vector2  pos      = rectCenter + (location.MapPosition + viewOffset) * zoom;

                    Rectangle drawRect = location.Type.Sprite.SourceRect;
                    drawRect.X = (int)pos.X - drawRect.Width / 2;
                    drawRect.Y = (int)pos.Y - drawRect.Width / 2;

                    if (!rect.Intersects(drawRect))
                    {
                        continue;
                    }

                    Color color = location.Type.SpriteColor;
                    if (location.Connections.Find(c => c.Locations.Contains(CurrentLocation)) == null)
                    {
                        color *= 0.5f;
                    }

                    float iconScale = location == CurrentLocation ? 1.2f : 1.0f;
                    if (location == highlightedLocation)
                    {
                        iconScale *= 1.1f;
                        color      = Color.Lerp(color, Color.White, 0.5f);
                    }

                    float distFromPlayer = Vector2.Distance(CurrentLocation.MapPosition, location.MapPosition);
                    color *= MathHelper.Clamp((1000.0f - distFromPlayer) / 500.0f, 0.1f, 1.0f);

                    location.Type.Sprite.Draw(spriteBatch, pos, color,
                                              scale: MapGenerationParams.Instance.LocationIconSize / location.Type.Sprite.size.X * iconScale * zoom);
                    MapGenerationParams.Instance.LocationIndicator.Draw(spriteBatch, pos, color,
                                                                        scale: MapGenerationParams.Instance.LocationIconSize / MapGenerationParams.Instance.LocationIndicator.size.X * iconScale * zoom * 1.4f);
                }

                //PLACEHOLDER until the stuff at the center of the map is implemented
                float   centerIconSize = 50.0f;
                Vector2 centerPos      = rectCenter + (new Vector2(size / 2) + viewOffset) * zoom;
                bool    mouseOn        = Vector2.Distance(PlayerInput.MousePosition, centerPos) < centerIconSize * zoom;

                var   centerLocationType = LocationType.List.Last();
                Color centerColor        = centerLocationType.SpriteColor * (mouseOn ? 1.0f : 0.6f);
                centerLocationType.Sprite.Draw(spriteBatch, centerPos, centerColor,
                                               scale: centerIconSize / centerLocationType.Sprite.size.X * zoom);
                MapGenerationParams.Instance.LocationIndicator.Draw(spriteBatch, centerPos, centerColor,
                                                                    scale: centerIconSize / MapGenerationParams.Instance.LocationIndicator.size.X * zoom * 1.2f);

                if (mouseOn && PlayerInput.LeftButtonClicked() && !messageBoxOpen)
                {
                    if (TextManager.ContainsTag("centerarealockedheader") && TextManager.ContainsTag("centerarealockedtext"))
                    {
                        var messageBox = new GUIMessageBox(
                            TextManager.Get("centerarealockedheader"),
                            TextManager.Get("centerarealockedtext"));
                        messageBoxOpen = true;
                        CoroutineManager.StartCoroutine(WaitForMessageBoxClosed(messageBox));
                    }
                    else
                    {
                        //if the message cannot be shown in the selected language,
                        //show the campaign roadmap (which mentions the center location not being reachable)
                        var messageBox = new GUIMessageBox(TextManager.Get("CampaignRoadMapTitle"), TextManager.Get("CampaignRoadMapText"));
                        messageBoxOpen = true;
                        CoroutineManager.StartCoroutine(WaitForMessageBoxClosed(messageBox));
                    }
                }
            }

            DrawDecorativeHUD(spriteBatch, rect);

            for (int i = 0; i < 2; i++)
            {
                Location location = (i == 0) ? highlightedLocation : CurrentLocation;
                if (location == null)
                {
                    continue;
                }

                Vector2 pos = rectCenter + (location.MapPosition + viewOffset) * zoom;
                pos.X += 25 * zoom;
                pos.Y -= 5 * zoom;
                Vector2 size = GUI.LargeFont.MeasureString(location.Name);
                GUI.Style.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0].Draw(
                    spriteBatch, new Rectangle((int)pos.X - 30, (int)pos.Y, (int)size.X + 60, (int)(size.Y + 25 * GUI.Scale)), Color.Black * hudOpenState * 0.7f);
                GUI.DrawString(spriteBatch, pos,
                               location.Name, Color.White * hudOpenState * 1.5f, font: GUI.LargeFont);
                GUI.DrawString(spriteBatch, pos + Vector2.UnitY * 25 * GUI.Scale,
                               location.Type.Name, Color.White * hudOpenState * 1.5f);
            }

            GameMain.Instance.GraphicsDevice.ScissorRectangle = prevScissorRect;
            spriteBatch.End();
            spriteBatch.Begin(SpriteSortMode.Deferred);
        }
Пример #3
0
        public void Draw(SpriteBatch spriteBatch, Rectangle rect, float scale = 1.0f)
        {
            Vector2 rectCenter = new Vector2(rect.Center.X, rect.Center.Y);
            Vector2 offset     = -currentLocation.MapPosition;

            iceTexture.DrawTiled(spriteBatch, new Vector2(rect.X, rect.Y), new Vector2(rect.Width, rect.Height), Vector2.Zero, Color.White * 0.8f);

            foreach (LocationConnection connection in connections)
            {
                Color crackColor = Color.White * Math.Max(connection.Difficulty / 100.0f, 1.5f);

                if (selectedLocation != currentLocation &&
                    (connection.Locations.Contains(selectedLocation) && connection.Locations.Contains(currentLocation)))
                {
                    crackColor = Color.Red;
                }
                else if (highlightedLocation != currentLocation &&
                         (connection.Locations.Contains(highlightedLocation) && connection.Locations.Contains(currentLocation)))
                {
                    crackColor = Color.Red * 0.5f;
                }
                else if (!connection.Passed)
                {
                    crackColor *= 0.2f;
                }

                for (int i = 0; i < connection.CrackSegments.Count; i++)
                {
                    var segment = connection.CrackSegments[i];

                    Vector2 start = rectCenter + (segment[0] + offset) * scale;
                    Vector2 end   = rectCenter + (segment[1] + offset) * scale;

                    if (!rect.Contains(start) && !rect.Contains(end))
                    {
                        continue;
                    }
                    else
                    {
                        Vector2?intersection = MathUtils.GetLineRectangleIntersection(start, end, new Rectangle(rect.X, rect.Y + rect.Height, rect.Width, rect.Height));
                        if (intersection != null)
                        {
                            if (!rect.Contains(start))
                            {
                                start = (Vector2)intersection;
                            }
                            else
                            {
                                end = (Vector2)intersection;
                            }
                        }
                    }

                    float dist = Vector2.Distance(start, end);

                    int width = (int)(MathHelper.Clamp(connection.Difficulty, 2.0f, 20.0f) * scale);

                    spriteBatch.Draw(iceCrack,
                                     new Rectangle((int)start.X, (int)start.Y, (int)dist + 2, width),
                                     new Rectangle(0, 0, iceCrack.Width, 60), crackColor, MathUtils.VectorToAngle(end - start),
                                     new Vector2(0, 30), SpriteEffects.None, 0.01f);
                }
            }

            rect.Inflate(8, 8);
            GUI.DrawRectangle(spriteBatch, rect, Color.Black, false, 0.0f, 8);
            GUI.DrawRectangle(spriteBatch, rect, Color.LightGray);

            for (int i = 0; i < locations.Count; i++)
            {
                Location location = locations[i];
                Vector2  pos      = rectCenter + (location.MapPosition + offset) * scale;

                Rectangle drawRect   = location.Type.Sprite.SourceRect;
                Rectangle sourceRect = drawRect;
                drawRect.X = (int)pos.X - drawRect.Width / 2;
                drawRect.Y = (int)pos.Y - drawRect.Width / 2;

                if (!rect.Intersects(drawRect))
                {
                    continue;
                }

                Color color = location.Connections.Find(c => c.Locations.Contains(currentLocation)) == null ? Color.White : Color.Green;

                color *= (location.Discovered) ? 0.8f : 0.2f;

                if (location == currentLocation)
                {
                    color = Color.Orange;
                }

                if (drawRect.X < rect.X)
                {
                    sourceRect.X     += rect.X - drawRect.X;
                    sourceRect.Width -= sourceRect.X;
                    drawRect.X        = rect.X;
                }
                else if (drawRect.Right > rect.Right)
                {
                    sourceRect.Width -= (drawRect.Right - rect.Right);
                }

                if (drawRect.Y < rect.Y)
                {
                    sourceRect.Y      += rect.Y - drawRect.Y;
                    sourceRect.Height -= sourceRect.Y;
                    drawRect.Y         = rect.Y;
                }
                else if (drawRect.Bottom > rect.Bottom)
                {
                    sourceRect.Height -= drawRect.Bottom - rect.Bottom;
                }

                drawRect.Width  = sourceRect.Width;
                drawRect.Height = sourceRect.Height;

                spriteBatch.Draw(location.Type.Sprite.Texture, drawRect, sourceRect, color);
            }

            for (int i = 0; i < 3; i++)
            {
                Location location = (i == 0) ? highlightedLocation : selectedLocation;
                if (i == 2)
                {
                    location = currentLocation;
                }

                if (location == null)
                {
                    continue;
                }

                Vector2 pos = rectCenter + (location.MapPosition + offset) * scale;
                pos.X = (int)(pos.X + location.Type.Sprite.SourceRect.Width * 0.6f);
                pos.Y = (int)(pos.Y - 10);
                GUI.DrawString(spriteBatch, pos, location.Name, Color.White, Color.Black * 0.8f, 3);
            }
        }
Пример #4
0
        private void GenerateRuin(List <VoronoiCell> mainPath)
        {
            Vector2 ruinSize   = new Vector2(Rand.Range(5000.0f, 8000.0f, Rand.RandSync.Server), Rand.Range(5000.0f, 8000.0f, Rand.RandSync.Server));
            float   ruinRadius = Math.Max(ruinSize.X, ruinSize.Y) * 0.5f;

            Vector2 ruinPos = cells[Rand.Int(cells.Count, Rand.RandSync.Server)].Center;

            //50% chance of placing the ruins at a cave
            if (Rand.Range(0.0f, 1.0f, Rand.RandSync.Server) < 0.5f)
            {
                TryGetInterestingPosition(true, PositionType.Cave, 0.0f, out ruinPos);
            }

            ruinPos.Y = Math.Min(ruinPos.Y, borders.Y + borders.Height - ruinSize.Y / 2);
            ruinPos.Y = Math.Max(ruinPos.Y, SeaFloorTopPos + ruinSize.Y / 2.0f);

            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;

                    weighedPathPos  += moveAmount;
                    weighedPathPos.Y = Math.Min(borders.Y + borders.Height - ruinSize.Y / 2, weighedPathPos.Y);
                }

                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(MathUtils.ToPoint(ruinPos - ruinSize * 0.5f), MathUtils.ToPoint(ruinSize)));

            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));

                foreach (VoronoiCell cell in tooClose)
                {
                    if (cell.CellType == CellType.Empty)
                    {
                        continue;
                    }
                    foreach (GraphEdge e in cell.edges)
                    {
                        Rectangle rect = ruinShape.Rect;
                        rect.Y += rect.Height;
                        if (ruinShape.Rect.Contains(e.point1) || ruinShape.Rect.Contains(e.point2) ||
                            MathUtils.GetLineRectangleIntersection(e.point1, e.point2, rect) != null)
                        {
                            cell.CellType = CellType.Removed;

                            int x = (int)Math.Floor(cell.Center.X / GridCellSize);
                            int y = (int)Math.Floor(cell.Center.Y / GridCellSize);

                            cellGrid[x, y].Remove(cell);
                            cells.Remove(cell);
                            break;
                        }
                    }
                }
            }
        }
Пример #5
0
        private void DrawConnection(SpriteBatch spriteBatch, LocationConnection connection, Rectangle viewArea, Vector2 viewOffset, Color?overrideColor = null)
        {
            Color connectionColor;

            if (GameMain.DebugDraw)
            {
                float sizeFactor = MathUtils.InverseLerp(
                    generationParams.SmallLevelConnectionLength,
                    generationParams.LargeLevelConnectionLength,
                    connection.Length);
                connectionColor = ToolBox.GradientLerp(sizeFactor, Color.LightGreen, GUI.Style.Orange, GUI.Style.Red);
            }
            else if (overrideColor.HasValue)
            {
                connectionColor = overrideColor.Value;
            }
            else
            {
                connectionColor = connection.Passed ? generationParams.ConnectionColor : generationParams.UnvisitedConnectionColor;
            }

            int width = (int)(generationParams.LocationConnectionWidth * zoom);

            if (Level.Loaded?.LevelData == connection.LevelData)
            {
                connectionColor = generationParams.HighlightedConnectionColor;
                width           = (int)(width * 1.5f);
            }
            if (SelectedLocation != CurrentDisplayLocation &&
                (connection.Locations.Contains(SelectedLocation) && connection.Locations.Contains(CurrentDisplayLocation)))
            {
                connectionColor = generationParams.HighlightedConnectionColor;
                width          *= 2;
            }
            else if (HighlightedLocation != CurrentDisplayLocation &&
                     (connection.Locations.Contains(HighlightedLocation) && connection.Locations.Contains(CurrentDisplayLocation)))
            {
                connectionColor = generationParams.HighlightedConnectionColor;
                width          *= 2;
            }

            Vector2 rectCenter = viewArea.Center.ToVector2();

            int startIndex = connection.CrackSegments.Count > 2 ? 1 : 0;
            int endIndex   = connection.CrackSegments.Count > 2 ? connection.CrackSegments.Count - 1 : connection.CrackSegments.Count;

            for (int i = startIndex; i < endIndex; i++)
            {
                var segment = connection.CrackSegments[i];

                Vector2 start = rectCenter + (segment[0] + viewOffset) * zoom;
                Vector2 end   = rectCenter + (segment[1] + viewOffset) * zoom;

                if (!viewArea.Contains(start) && !viewArea.Contains(end))
                {
                    continue;
                }
                else
                {
                    if (MathUtils.GetLineRectangleIntersection(start, end, new Rectangle(viewArea.X, viewArea.Y + viewArea.Height, viewArea.Width, viewArea.Height), out Vector2 intersection))
                    {
                        if (!viewArea.Contains(start))
                        {
                            start = intersection;
                        }
                        else
                        {
                            end = intersection;
                        }
                    }
                }

                float a = 1.0f;
                if (!connection.Locations[0].Discovered && !connection.Locations[1].Discovered)
                {
                    if (IsInFogOfWar(connection.Locations[0]))
                    {
                        a = (float)i / connection.CrackSegments.Count;
                    }
                    else if (IsInFogOfWar(connection.Locations[1]))
                    {
                        a = 1.0f - (float)i / connection.CrackSegments.Count;
                    }
                }
                float dist             = Vector2.Distance(start, end);
                var   connectionSprite = connection.Passed ? generationParams.PassedConnectionSprite : generationParams.ConnectionSprite;
                spriteBatch.Draw(connectionSprite.Texture,
                                 new Rectangle((int)start.X, (int)start.Y, (int)(dist - 1 * zoom), width),
                                 connectionSprite.SourceRect, connectionColor * a, MathUtils.VectorToAngle(end - start),
                                 new Vector2(0, connectionSprite.size.Y / 2), SpriteEffects.None, 0.01f);
            }

            if (GameMain.DebugDraw && zoom > 1.0f && generationParams.ShowLevelTypeNames)
            {
                Vector2 center = rectCenter + (connection.CenterPos + viewOffset) * zoom;
                if (viewArea.Contains(center) && connection.Biome != null)
                {
                    GUI.DrawString(spriteBatch, center, connection.Biome.Identifier + " (" + connection.Difficulty + ")", Color.White);
                }
            }
        }
Пример #6
0
        private void DrawConnection(SpriteBatch spriteBatch, LocationConnection connection, Rectangle viewArea, Vector2 viewOffset, Color?overrideColor = null)
        {
            Color connectionColor;

            if (GameMain.DebugDraw)
            {
                float sizeFactor = MathUtils.InverseLerp(
                    generationParams.SmallLevelConnectionLength,
                    generationParams.LargeLevelConnectionLength,
                    connection.Length);
                connectionColor = ToolBox.GradientLerp(sizeFactor, Color.LightGreen, GUI.Style.Orange, GUI.Style.Red);
            }
            else if (overrideColor.HasValue)
            {
                connectionColor = overrideColor.Value;
            }
            else
            {
                connectionColor = connection.Passed ? generationParams.ConnectionColor : generationParams.UnvisitedConnectionColor;
            }

            int width = (int)(generationParams.LocationConnectionWidth * zoom);

            if (Level.Loaded?.LevelData == connection.LevelData)
            {
                connectionColor = generationParams.HighlightedConnectionColor;
                width           = (int)(width * 1.5f);
            }
            if (SelectedLocation != CurrentDisplayLocation &&
                (connection.Locations.Contains(SelectedLocation) && connection.Locations.Contains(CurrentDisplayLocation)))
            {
                connectionColor = generationParams.HighlightedConnectionColor;
                width          *= 2;
            }
            else if (HighlightedLocation != CurrentDisplayLocation &&
                     (connection.Locations.Contains(HighlightedLocation) && connection.Locations.Contains(CurrentDisplayLocation)))
            {
                connectionColor = generationParams.HighlightedConnectionColor;
                width          *= 2;
            }

            Vector2 rectCenter = viewArea.Center.ToVector2();

            int startIndex = connection.CrackSegments.Count > 2 ? 1 : 0;
            int endIndex   = connection.CrackSegments.Count > 2 ? connection.CrackSegments.Count - 1 : connection.CrackSegments.Count;

            Vector2?connectionStart = null;
            Vector2?connectionEnd   = null;

            for (int i = startIndex; i < endIndex; i++)
            {
                var segment = connection.CrackSegments[i];

                Vector2 start = rectCenter + (segment[0] + viewOffset) * zoom;
                if (!connectionStart.HasValue)
                {
                    connectionStart = start;
                }
                Vector2 end = rectCenter + (segment[1] + viewOffset) * zoom;
                connectionEnd = end;

                if (!viewArea.Contains(start) && !viewArea.Contains(end))
                {
                    continue;
                }
                else
                {
                    if (MathUtils.GetLineRectangleIntersection(start, end, new Rectangle(viewArea.X, viewArea.Y + viewArea.Height, viewArea.Width, viewArea.Height), out Vector2 intersection))
                    {
                        if (!viewArea.Contains(start))
                        {
                            start = intersection;
                        }
                        else
                        {
                            end = intersection;
                        }
                    }
                }

                float a = 1.0f;
                if (!connection.Locations[0].Discovered && !connection.Locations[1].Discovered)
                {
                    if (IsInFogOfWar(connection.Locations[0]))
                    {
                        a = (float)i / connection.CrackSegments.Count;
                    }
                    else if (IsInFogOfWar(connection.Locations[1]))
                    {
                        a = 1.0f - (float)i / connection.CrackSegments.Count;
                    }
                }
                float dist             = Vector2.Distance(start, end);
                var   connectionSprite = connection.Passed ? generationParams.PassedConnectionSprite : generationParams.ConnectionSprite;
                spriteBatch.Draw(connectionSprite.Texture,
                                 new Rectangle((int)start.X, (int)start.Y, (int)(dist - 1 * zoom), width),
                                 connectionSprite.SourceRect, connectionColor * a, MathUtils.VectorToAngle(end - start),
                                 new Vector2(0, connectionSprite.size.Y / 2), SpriteEffects.None, 0.01f);
            }
            if (connectionStart.HasValue && connectionEnd.HasValue)
            {
                GUIComponentStyle crushDepthWarningIconStyle = null;
                string            tooltip = null;
                var subCrushDepth         = Submarine.MainSub?.RealWorldCrushDepth ?? Level.DefaultRealWorldCrushDepth;
                if (GameMain.GameSession?.Campaign?.UpgradeManager != null)
                {
                    var hullUpgradePrefab = UpgradePrefab.Find("increasewallhealth");
                    if (hullUpgradePrefab != null)
                    {
                        int pendingLevel = GameMain.GameSession.Campaign.UpgradeManager.GetUpgradeLevel(hullUpgradePrefab, hullUpgradePrefab.UpgradeCategories.First());
                        int currentLevel = GameMain.GameSession.Campaign.UpgradeManager.GetRealUpgradeLevel(hullUpgradePrefab, hullUpgradePrefab.UpgradeCategories.First());
                        if (pendingLevel > currentLevel)
                        {
                            string updateValueStr = hullUpgradePrefab.SourceElement?.Element("Structure")?.GetAttributeString("crushdepth", null);
                            if (!string.IsNullOrEmpty(updateValueStr))
                            {
                                subCrushDepth = PropertyReference.CalculateUpgrade(subCrushDepth, pendingLevel - currentLevel, updateValueStr);
                            }
                        }
                    }
                }

                if (connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio > subCrushDepth)
                {
                    crushDepthWarningIconStyle = GUI.Style.GetComponentStyle("CrushDepthWarningHighIcon");
                    tooltip = "crushdepthwarninghigh";
                }
                else if ((connection.LevelData.InitialDepth + connection.LevelData.Size.Y) * Physics.DisplayToRealWorldRatio > subCrushDepth)
                {
                    crushDepthWarningIconStyle = GUI.Style.GetComponentStyle("CrushDepthWarningLowIcon");
                    tooltip = "crushdepthwarninglow";
                }

                if (crushDepthWarningIconStyle != null)
                {
                    Vector2 iconPos  = (connectionStart.Value + connectionEnd.Value) / 2;
                    float   iconSize = 32.0f * GUI.Scale;
                    bool    mouseOn  = HighlightedLocation == null && Vector2.DistanceSquared(iconPos, PlayerInput.MousePosition) < iconSize * iconSize;
                    Sprite  crushDepthWarningIcon = crushDepthWarningIconStyle.GetDefaultSprite();
                    crushDepthWarningIcon.Draw(spriteBatch, iconPos,
                                               mouseOn ? crushDepthWarningIconStyle.HoverColor : crushDepthWarningIconStyle.Color,
                                               scale: iconSize / crushDepthWarningIcon.size.X);
                    if (mouseOn)
                    {
                        connectionTooltip = new Pair <Rectangle, string>(
                            new Rectangle(iconPos.ToPoint(), new Point((int)iconSize)),
                            TextManager.Get(tooltip)
                            .Replace("[initialdepth]", ((int)(connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio)).ToString())
                            .Replace("[submarinecrushdepth]", ((int)subCrushDepth).ToString()));
                    }
                }
            }

            if (GameMain.DebugDraw && zoom > 1.0f && generationParams.ShowLevelTypeNames)
            {
                Vector2 center = rectCenter + (connection.CenterPos + viewOffset) * zoom;
                if (viewArea.Contains(center) && connection.Biome != null)
                {
                    GUI.DrawString(spriteBatch, center, connection.Biome.Identifier + " (" + connection.Difficulty + ")", Color.White);
                }
            }
        }
Пример #7
0
        public void Draw(SpriteBatch spriteBatch, GUICustomComponent mapContainer)
        {
            Rectangle rect = mapContainer.Rect;

            Vector2 viewSize   = new Vector2(rect.Width / zoom, rect.Height / zoom);
            float   edgeBuffer = size * (BackgroundScale - 1.0f) / 2;

            drawOffset.X = MathHelper.Clamp(drawOffset.X, -size - edgeBuffer + viewSize.X / 2.0f, edgeBuffer - viewSize.X / 2.0f);
            drawOffset.Y = MathHelper.Clamp(drawOffset.Y, -size - edgeBuffer + viewSize.Y / 2.0f, edgeBuffer - viewSize.Y / 2.0f);

            drawOffsetNoise = new Vector2(
                (float)PerlinNoise.Perlin(Timing.TotalTime * 0.1f % 255, Timing.TotalTime * 0.1f % 255, 0) - 0.5f,
                (float)PerlinNoise.Perlin(Timing.TotalTime * 0.2f % 255, Timing.TotalTime * 0.2f % 255, 0.5f) - 0.5f) * 10.0f;

            Vector2 viewOffset = drawOffset + drawOffsetNoise;

            Vector2 rectCenter = new Vector2(rect.Center.X, rect.Center.Y);

            Rectangle prevScissorRect = GameMain.Instance.GraphicsDevice.ScissorRectangle;

            spriteBatch.End();
            spriteBatch.GraphicsDevice.ScissorRectangle = Rectangle.Intersect(prevScissorRect, rect);
            spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);

            for (int x = 0; x < mapTiles.GetLength(0); x++)
            {
                for (int y = 0; y < mapTiles.GetLength(1); y++)
                {
                    Vector2 mapPos = new Vector2(
                        x * generationParams.TileSpriteSpacing.X + ((y % 2 == 0) ? 0.0f : generationParams.TileSpriteSpacing.X * 0.5f),
                        y * generationParams.TileSpriteSpacing.Y);

                    mapPos.X -= size / 2 * (BackgroundScale - 1.0f);
                    mapPos.Y -= size / 2 * (BackgroundScale - 1.0f);

                    Vector2 scale = new Vector2(
                        generationParams.TileSpriteSize.X / mapTiles[x, y].Sprite.size.X,
                        generationParams.TileSpriteSize.Y / mapTiles[x, y].Sprite.size.Y);
                    mapTiles[x, y].Sprite.Draw(spriteBatch, rectCenter + (mapPos + viewOffset) * zoom, Color.White,
                                               origin: new Vector2(256.0f, 256.0f), rotate: 0, scale: scale * zoom, spriteEffect: mapTiles[x, y].SpriteEffect);
                }
            }
#if DEBUG
            if (generationParams.ShowNoiseMap)
            {
                GUI.DrawRectangle(spriteBatch, rectCenter + (borders.Location.ToVector2() + viewOffset) * zoom, borders.Size.ToVector2() * zoom, Color.White, true);
            }
#endif
            Vector2 topLeft = rectCenter + viewOffset * zoom;
            topLeft.X = (int)topLeft.X;
            topLeft.Y = (int)topLeft.Y;

            Vector2 bottomRight = rectCenter + (viewOffset + new Vector2(size, size)) * zoom;
            bottomRight.X = (int)bottomRight.X;
            bottomRight.Y = (int)bottomRight.Y;

            spriteBatch.Draw(noiseTexture,
                             destinationRectangle: new Rectangle((int)topLeft.X, (int)topLeft.Y, (int)(bottomRight.X - topLeft.X), (int)(bottomRight.Y - topLeft.Y)),
                             sourceRectangle: null,
                             color: Color.White);

            if (topLeft.X > rect.X)
            {
                GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Y, (int)(topLeft.X - rect.X), rect.Height), Color.Black * 0.8f, true);
            }
            if (topLeft.Y > rect.Y)
            {
                GUI.DrawRectangle(spriteBatch, new Rectangle((int)topLeft.X, rect.Y, (int)(bottomRight.X - topLeft.X), (int)(topLeft.Y - rect.Y)), Color.Black * 0.8f, true);
            }
            if (bottomRight.X < rect.Right)
            {
                GUI.DrawRectangle(spriteBatch, new Rectangle((int)bottomRight.X, rect.Y, (int)(rect.Right - bottomRight.X), rect.Height), Color.Black * 0.8f, true);
            }
            if (bottomRight.Y < rect.Bottom)
            {
                GUI.DrawRectangle(spriteBatch, new Rectangle((int)topLeft.X, (int)bottomRight.Y, (int)(bottomRight.X - topLeft.X), (int)(rect.Bottom - bottomRight.Y)), Color.Black * 0.8f, true);
            }

            var   sourceRect    = rect;
            float rawNoiseScale = 1.0f + Noise[(int)(Timing.TotalTime * 100 % Noise.GetLength(0) - 1), (int)(Timing.TotalTime * 100 % Noise.GetLength(1) - 1)];
            cameraNoiseStrength = Noise[(int)(Timing.TotalTime * 10 % Noise.GetLength(0) - 1), (int)(Timing.TotalTime * 10 % Noise.GetLength(1) - 1)];

            rawNoiseSprite.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(),
                                     startOffset: new Point(Rand.Range(0, rawNoiseSprite.SourceRect.Width), Rand.Range(0, rawNoiseSprite.SourceRect.Height)),
                                     color: Color.White * cameraNoiseStrength * 0.5f,
                                     textureScale: Vector2.One * rawNoiseScale);

            if (generationParams.ShowLocations)
            {
                foreach (LocationConnection connection in connections)
                {
                    Color connectionColor;
                    if (GameMain.DebugDraw)
                    {
                        float sizeFactor = MathUtils.InverseLerp(
                            MapGenerationParams.Instance.SmallLevelConnectionLength,
                            MapGenerationParams.Instance.LargeLevelConnectionLength,
                            connection.Length);

                        connectionColor = ToolBox.GradientLerp(sizeFactor, Color.LightGreen, Color.Orange, Color.Red);
                    }
                    else
                    {
                        connectionColor = ToolBox.GradientLerp(connection.Difficulty / 100.0f,
                                                               MapGenerationParams.Instance.LowDifficultyColor,
                                                               MapGenerationParams.Instance.MediumDifficultyColor,
                                                               MapGenerationParams.Instance.HighDifficultyColor);
                    }

                    int width = (int)(3 * zoom);

                    if (selectedLocation != currentLocation &&
                        (connection.Locations.Contains(selectedLocation) && connection.Locations.Contains(currentLocation)))
                    {
                        connectionColor = Color.Gold;
                    }
                    else if (highlightedLocation != currentLocation &&
                             (connection.Locations.Contains(highlightedLocation) && connection.Locations.Contains(currentLocation)))
                    {
                        connectionColor = Color.Lerp(connectionColor, Color.White, 0.5f);
                        width          *= 2;
                    }
                    else if (!connection.Passed)
                    {
                        //crackColor *= 0.5f;
                    }

                    for (int i = 0; i < connection.CrackSegments.Count; i++)
                    {
                        var segment = connection.CrackSegments[i];

                        Vector2 start = rectCenter + (segment[0] + viewOffset) * zoom;
                        Vector2 end   = rectCenter + (segment[1] + viewOffset) * zoom;

                        if (!rect.Contains(start) && !rect.Contains(end))
                        {
                            continue;
                        }
                        else
                        {
                            Vector2?intersection = MathUtils.GetLineRectangleIntersection(start, end, new Rectangle(rect.X, rect.Y + rect.Height, rect.Width, rect.Height));
                            if (intersection != null)
                            {
                                if (!rect.Contains(start))
                                {
                                    start = (Vector2)intersection;
                                }
                                else
                                {
                                    end = (Vector2)intersection;
                                }
                            }
                        }

                        float distFromPlayer = Vector2.Distance(currentLocation.MapPosition, (segment[0] + segment[1]) / 2.0f);
                        float dist           = Vector2.Distance(start, end);

                        float a = GameMain.DebugDraw ? 1.0f : (200.0f - distFromPlayer) / 200.0f;
                        spriteBatch.Draw(generationParams.ConnectionSprite.Texture,
                                         new Rectangle((int)start.X, (int)start.Y, (int)(dist - 1 * zoom), width),
                                         null, connectionColor * MathHelper.Clamp(a, 0.1f, 0.5f), MathUtils.VectorToAngle(end - start),
                                         new Vector2(0, 16), SpriteEffects.None, 0.01f);
                    }

                    if (GameMain.DebugDraw && zoom > 1.0f && generationParams.ShowLevelTypeNames)
                    {
                        Vector2 center = rectCenter + (connection.CenterPos + viewOffset) * zoom;
                        if (rect.Contains(center))
                        {
                            GUI.DrawString(spriteBatch, center, connection.Biome.Name + " (" + connection.Difficulty + ")", Color.White);
                        }
                    }
                }

                rect.Inflate(8, 8);
                GUI.DrawRectangle(spriteBatch, rect, Color.Black, false, 0.0f, 8);
                GUI.DrawRectangle(spriteBatch, rect, Color.LightGray);

                for (int i = 0; i < locations.Count; i++)
                {
                    Location location = locations[i];
                    Vector2  pos      = rectCenter + (location.MapPosition + viewOffset) * zoom;

                    float iconScale = MapGenerationParams.Instance.LocationIconSize / location.Type.Sprite.size.X;

                    Rectangle drawRect = location.Type.Sprite.SourceRect;
                    drawRect.X = (int)pos.X - drawRect.Width / 2;
                    drawRect.Y = (int)pos.Y - drawRect.Width / 2;

                    if (!rect.Intersects(drawRect))
                    {
                        continue;
                    }

                    Color color = location.Type.SpriteColor;

                    if (location.Connections.Find(c => c.Locations.Contains(currentLocation)) == null)
                    {
                        color *= 0.5f;
                    }
                    //color *= (location.Discovered) ? 0.8f : 0.5f;
                    //if (location != currentLocation) color *= 1.0f;
                    if (location == highlightedLocation)
                    {
                        iconScale *= 1.1f;
                        color      = Color.Lerp(color, Color.White, 0.5f);
                    }

                    location.Type.Sprite.Draw(spriteBatch, pos, color, scale: iconScale * zoom);
                }
            }

            DrawDecorativeHUD(spriteBatch, rect);

            for (int i = 0; i < 3; i++)
            {
                Location location = (i == 0) ? highlightedLocation : selectedLocation;
                if (i == 2)
                {
                    location = currentLocation;
                }

                if (location == null)
                {
                    continue;
                }

                Vector2 pos = rectCenter + (location.MapPosition + viewOffset) * zoom;
                //pos.X = (int)(pos.X + location.Type.Sprite.SourceRect.Width * 0.6f);
                pos.Y = (int)(pos.Y + 15 * zoom);
                GUI.DrawString(spriteBatch, pos - GUI.Font.MeasureString(location.Name) * 0.5f,
                               location.Name, Color.White * hudOpenState, Color.Black * 0.8f * hudOpenState, 3);
                GUI.DrawString(spriteBatch, pos + Vector2.UnitY * 25 - GUI.Font.MeasureString(location.Type.DisplayName) * 0.5f,
                               location.Type.DisplayName, Color.White * hudOpenState, Color.Black * 0.8f * hudOpenState, 3);
            }

            GameMain.Instance.GraphicsDevice.ScissorRectangle = prevScissorRect;
            spriteBatch.End();
            spriteBatch.Begin(SpriteSortMode.Deferred);
        }