Esempio n. 1
0
        public void MoveCamera(float deltaTime, bool allowMove = true, bool allowZoom = true)
        {
            prevPosition = position;
            prevZoom     = zoom;

            float moveSpeed = 20.0f / zoom;

            Vector2 moveCam = Vector2.Zero;

            if (targetPos == Vector2.Zero)
            {
                Vector2 moveInput = Vector2.Zero;
                if (allowMove && !Freeze)
                {
                    if (GUI.KeyboardDispatcher.Subscriber == null)
                    {
                        if (PlayerInput.KeyDown(Keys.LeftShift))
                        {
                            moveSpeed *= 2.0f;
                        }
                        if (PlayerInput.KeyDown(Keys.LeftControl))
                        {
                            moveSpeed *= 0.5f;
                        }

                        if (GameMain.Config.KeyBind(InputType.Left).IsDown())
                        {
                            moveInput.X -= 1.0f;
                        }
                        if (GameMain.Config.KeyBind(InputType.Right).IsDown())
                        {
                            moveInput.X += 1.0f;
                        }
                        if (GameMain.Config.KeyBind(InputType.Down).IsDown())
                        {
                            moveInput.Y -= 1.0f;
                        }
                        if (GameMain.Config.KeyBind(InputType.Up).IsDown())
                        {
                            moveInput.Y += 1.0f;
                        }
                    }

                    velocity = Vector2.Lerp(velocity, moveInput, deltaTime * 10.0f);
                    moveCam  = velocity * moveSpeed * deltaTime * 60.0f;

                    if (Screen.Selected == GameMain.GameScreen && FollowSub)
                    {
                        var closestSub = Submarine.FindClosest(WorldViewCenter);
                        if (closestSub != null)
                        {
                            moveCam += FarseerPhysics.ConvertUnits.ToDisplayUnits(closestSub.Velocity * deltaTime);
                        }
                    }
                }

                if (allowZoom && GUI.MouseOn == null)
                {
                    Vector2 mouseInWorld = ScreenToWorld(PlayerInput.MousePosition);
                    Vector2 diffViewCenter;
                    diffViewCenter = ((mouseInWorld - Position) * Zoom);
                    targetZoom     = MathHelper.Clamp(
                        targetZoom + (PlayerInput.ScrollWheelSpeed / 1000.0f) * zoom,
                        GameMain.DebugDraw ? MinZoom * 0.1f : MinZoom,
                        MaxZoom);

                    Zoom = MathHelper.Lerp(Zoom, targetZoom, deltaTime * 10.0f);
                    if (!PlayerInput.KeyDown(Keys.F))
                    {
                        Position = mouseInWorld - (diffViewCenter / Zoom);
                    }
                }
            }
            else if (allowMove)
            {
                Vector2 mousePos = PlayerInput.MousePosition;
                Vector2 offset   = mousePos - resolution.ToVector2() / 2;
                offset.X = offset.X / (resolution.X * 0.4f);
                offset.Y = -offset.Y / (resolution.Y * 0.3f);
                if (offset.LengthSquared() > 1.0f)
                {
                    offset.Normalize();
                }
                offset *= offsetAmount;
                // Freeze the camera movement by default, when the cursor is on top of an ui element.
                // Setting a positive value to the OffsetAmount, will override this behaviour.
                if (GUI.MouseOn != null && offsetAmount > 0)
                {
                    Freeze = true;
                }
                if (CharacterHealth.OpenHealthWindow != null || CrewManager.IsCommandInterfaceOpen || ConversationAction.IsDialogOpen)
                {
                    offset *= 0;
                    Freeze  = false;
                }
                if (Freeze)
                {
                    offset = previousOffset;
                }
                else
                {
                    previousOffset = offset;
                }

                //how much to zoom out (zoom completely out when offset is 1000)
                float zoomOutAmount = Math.Min(offset.Length() / 1000.0f, 1.0f);
                //zoom amount when resolution is not taken into account
                float unscaledZoom = MathHelper.Lerp(DefaultZoom, MinZoom, zoomOutAmount);
                //zoom with resolution taken into account (zoom further out on smaller resolutions)
                float scaledZoom = unscaledZoom * globalZoomScale;

                //an ad-hoc way of allowing the players to have roughly the same maximum view distance regardless of the resolution,
                //while still keeping the zoom around 1.0 when not looking further away (because otherwise we'd always be downsampling
                //on lower resolutions, which doesn't look that good)
                float newZoom = MathHelper.Lerp(unscaledZoom, scaledZoom,
                                                (GameMain.Config == null || GameMain.Config.EnableMouseLook) ? (float)Math.Sqrt(zoomOutAmount) : 0.3f);

                Zoom += (newZoom - zoom) / ZoomSmoothness;

                //force targetzoom to the current zoom value, so the camera stays at the same zoom when switching to freecam
                targetZoom = Zoom;

                Vector2 diff = (targetPos + offset) - position;

                moveCam = diff / MoveSmoothness;
            }
            rotation        += angularVelocity * deltaTime;
            angularVelocity *= (1.0f - angularDamping);
            angularVelocity += -rotation * angularSpring;

            angularDamping = 0.05f;
            angularSpring  = 0.2f;

            if (Shake < 0.01f)
            {
                shakePosition = Vector2.Zero;
                shakeTimer    = 0.0f;
            }
            else
            {
                shakeTimer += deltaTime * 5.0f;
                Vector2 noisePos = new Vector2((float)PerlinNoise.CalculatePerlin(shakeTimer, shakeTimer, 0) - 0.5f, (float)PerlinNoise.CalculatePerlin(shakeTimer, shakeTimer, 0.5f) - 0.5f);

                shakePosition = noisePos * Shake * 2.0f;
                Shake         = MathHelper.Lerp(Shake, 0.0f, deltaTime * 2.0f);
            }

            Translate(moveCam + shakePosition);
            Freeze = false;
        }
Esempio n. 2
0
        public void Draw(SpriteBatch spriteBatch, GUICustomComponent mapContainer)
        {
            Rectangle rect = mapContainer.Rect;

            Vector2 viewSize   = new Vector2(rect.Width / zoom, rect.Height / zoom);
            Vector2 edgeBuffer = rect.Size.ToVector2() / 2;

            DrawOffset.X = MathHelper.Clamp(DrawOffset.X, -Width - edgeBuffer.X + viewSize.X / 2.0f, edgeBuffer.X - viewSize.X / 2.0f);
            DrawOffset.Y = MathHelper.Clamp(DrawOffset.Y, -Height - edgeBuffer.Y + viewSize.Y / 2.0f, edgeBuffer.Y - 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, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);

            Vector2 topLeft     = rectCenter + viewOffset;
            Vector2 bottomRight = rectCenter + (viewOffset + new Vector2(Width, Height));
            Vector2 mapTileSize = mapTiles[0, 0].size * generationParams.MapTileScale;

            int startX = (int)Math.Floor(-topLeft.X / mapTileSize.X) - 1;
            int startY = (int)Math.Floor(-topLeft.Y / mapTileSize.Y) - 1;
            int endX   = (int)Math.Ceiling((-topLeft.X + rect.Width) / mapTileSize.X);
            int endY   = (int)Math.Ceiling((-topLeft.Y + rect.Height) / mapTileSize.Y);

            float noiseT = (float)(Timing.TotalTime * 0.01f);

            cameraNoiseStrength = (float)PerlinNoise.CalculatePerlin(noiseT, noiseT * 0.5f, noiseT * 0.2f);
            float noiseScale = (float)PerlinNoise.CalculatePerlin(noiseT * 5.0f, noiseT * 2.0f, 0) * 5.0f;

            for (int x = startX; x <= endX; x++)
            {
                for (int y = startY; y <= endY; y++)
                {
                    int     tileX   = Math.Abs(x) % mapTiles.GetLength(0);
                    int     tileY   = Math.Abs(y) % mapTiles.GetLength(1);
                    Vector2 tilePos = rectCenter + (viewOffset + new Vector2(x, y) * mapTileSize) * zoom;
                    mapTiles[tileX, tileY].Draw(spriteBatch, tilePos, Color.White, origin: Vector2.Zero, scale: generationParams.MapTileScale * zoom);

                    if (GameMain.DebugDraw)
                    {
                        continue;
                    }
                    if (!tileDiscovered[tileX, tileY] || x < 0 || y < 0 || x >= tileDiscovered.GetLength(0) || y >= tileDiscovered.GetLength(1))
                    {
                        generationParams.FogOfWarSprite?.Draw(spriteBatch, tilePos, Color.White * cameraNoiseStrength, origin: Vector2.Zero, scale: generationParams.MapTileScale * zoom);
                        noiseOverlay.DrawTiled(spriteBatch, tilePos, mapTileSize * zoom,
                                               startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
                                               color: Color.White * cameraNoiseStrength * 0.2f,
                                               textureScale: Vector2.One * noiseScale);
                    }
                }
            }

            if (GameMain.DebugDraw)
            {
                if (topLeft.X > rect.X)
                {
                    GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Y, (int)(topLeft.X - rect.X), rect.Height), Color.Black * 0.5f, 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.5f, 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.5f, 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.5f, true);
                }
            }

            float rawNoiseScale = 1.0f + PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1));

            cameraNoiseStrength = PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1));

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

            noiseOverlay.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(),
                                   startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
                                   color: new Color(20, 20, 20, 50),
                                   textureScale: Vector2.One * rawNoiseScale * 2);

            noiseOverlay.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight),
                                   startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
                                   color: Color.White * cameraNoiseStrength * 0.1f,
                                   textureScale: Vector2.One * noiseScale);

            Pair <Rectangle, string> tooltip = null;

            if (generationParams.ShowLocations)
            {
                foreach (LocationConnection connection in Connections)
                {
                    if (IsInFogOfWar(connection.Locations[0]) && IsInFogOfWar(connection.Locations[1]))
                    {
                        continue;
                    }
                    DrawConnection(spriteBatch, connection, rect, viewOffset);
                }

                for (int i = 0; i < Locations.Count; i++)
                {
                    Location location = Locations[i];
                    if (IsInFogOfWar(location))
                    {
                        continue;
                    }
                    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;
                    }

                    if (location == CurrentDisplayLocation)
                    {
                        generationParams.CurrentLocationIndicator.Draw(spriteBatch,
                                                                       rectCenter + (currLocationIndicatorPos + viewOffset) * zoom,
                                                                       generationParams.IndicatorColor,
                                                                       generationParams.CurrentLocationIndicator.Origin, 0, Vector2.One * (generationParams.LocationIconSize / generationParams.CurrentLocationIndicator.size.X) * 1.7f * zoom);
                    }

                    if (location == SelectedLocation)
                    {
                        generationParams.SelectedLocationIndicator.Draw(spriteBatch,
                                                                        rectCenter + (location.MapPosition + viewOffset) * zoom,
                                                                        generationParams.IndicatorColor,
                                                                        generationParams.SelectedLocationIndicator.Origin, 0, Vector2.One * (generationParams.LocationIconSize / generationParams.SelectedLocationIndicator.size.X) * 1.7f * zoom);
                    }

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

                    float iconScale = location == CurrentDisplayLocation ? 1.2f : 1.0f;
                    if (location == HighlightedLocation)
                    {
                        iconScale *= 1.2f;
                    }

                    location.Type.Sprite.Draw(spriteBatch, pos, color,
                                              scale: generationParams.LocationIconSize / location.Type.Sprite.size.X * iconScale * zoom);
                    if (location.TypeChangeTimer <= 0 && !string.IsNullOrEmpty(location.LastTypeChangeMessage) && generationParams.TypeChangeIcon != null)
                    {
                        Vector2 typeChangeIconPos   = pos + new Vector2(1.35f, -0.35f) * generationParams.LocationIconSize * 0.5f * zoom;
                        float   typeChangeIconScale = 18.0f / generationParams.TypeChangeIcon.SourceRect.Width;
                        generationParams.TypeChangeIcon.Draw(spriteBatch, typeChangeIconPos, GUI.Style.Red, scale: typeChangeIconScale * zoom);
                        if (Vector2.Distance(PlayerInput.MousePosition, typeChangeIconPos) < generationParams.TypeChangeIcon.SourceRect.Width * zoom)
                        {
                            tooltip = new Pair <Rectangle, string>(
                                new Rectangle(typeChangeIconPos.ToPoint(), new Point(30)),
                                location.LastTypeChangeMessage);
                        }
                    }
                    if (location != CurrentLocation && CurrentLocation.AvailableMissions.Any(m => m.Locations.Contains(location)) && generationParams.MissionIcon != null)
                    {
                        Vector2 missionIconPos   = pos + new Vector2(1.35f, 0.35f) * generationParams.LocationIconSize * 0.5f * zoom;
                        float   missionIconScale = 18.0f / generationParams.MissionIcon.SourceRect.Width;
                        generationParams.MissionIcon.Draw(spriteBatch, missionIconPos, generationParams.IndicatorColor, scale: missionIconScale * zoom);
                        if (Vector2.Distance(PlayerInput.MousePosition, missionIconPos) < generationParams.MissionIcon.SourceRect.Width * zoom)
                        {
                            var availableMissions = CurrentLocation.AvailableMissions.Where(m => m.Locations.Contains(location));
                            tooltip = new Pair <Rectangle, string>(
                                new Rectangle(missionIconPos.ToPoint(), new Point(30)),
                                TextManager.Get("mission") + '\n' + string.Join('\n', availableMissions.Select(m => "- " + m.Name)));
                        }
                    }

                    if (GameMain.DebugDraw && location == HighlightedLocation && (!location.Discovered || !location.Type.HasOutpost))
                    {
                        if (location.Reputation != null)
                        {
                            Vector2 dPos = pos;
                            dPos.Y += 48;
                            string  name     = $"Reputation: {location.Name}";
                            Vector2 nameSize = GUI.SmallFont.MeasureString(name);
                            GUI.DrawString(spriteBatch, dPos, name, Color.White, Color.Black * 0.8f, 4, font: GUI.SmallFont);
                            dPos.Y += nameSize.Y + 16;

                            Rectangle bgRect = new Rectangle((int)dPos.X, (int)dPos.Y, 256, 32);
                            bgRect.Inflate(8, 8);
                            Color barColor = ToolBox.GradientLerp(location.Reputation.NormalizedValue, Color.Red, Color.Yellow, Color.LightGreen);
                            GUI.DrawRectangle(spriteBatch, bgRect, Color.Black * 0.8f, isFilled: true);
                            GUI.DrawRectangle(spriteBatch, new Rectangle((int)dPos.X, (int)dPos.Y, (int)(location.Reputation.NormalizedValue * 255), 32), barColor, isFilled: true);
                            string  reputationValue = ((int)location.Reputation.Value).ToString();
                            Vector2 repValueSize    = GUI.SubHeadingFont.MeasureString(reputationValue);
                            GUI.DrawString(spriteBatch, dPos + (new Vector2(256, 32) / 2) - (repValueSize / 2), reputationValue, Color.White, Color.Black, font: GUI.SubHeadingFont);
                            GUI.DrawRectangle(spriteBatch, new Rectangle((int)dPos.X, (int)dPos.Y, 256, 32), Color.White);
                        }
                    }
                }
            }

            DrawDecorativeHUD(spriteBatch, rect);

            if (HighlightedLocation != null)
            {
                Vector2 pos = rectCenter + (HighlightedLocation.MapPosition + viewOffset) * zoom;
                pos.X += 50 * zoom;
                Vector2 nameSize = GUI.LargeFont.MeasureString(HighlightedLocation.Name);
                Vector2 typeSize = GUI.Font.MeasureString(HighlightedLocation.Type.Name);
                Vector2 size = new Vector2(Math.Max(nameSize.X, typeSize.X), nameSize.Y + typeSize.Y);
                bool    showReputation = HighlightedLocation.Discovered && HighlightedLocation.Type.HasOutpost && HighlightedLocation.Reputation != null;
                string  repLabelText = null, repValueText = null;
                Vector2 repLabelSize = Vector2.Zero, repBarSize = Vector2.Zero;
                if (showReputation)
                {
                    repLabelText = TextManager.Get("reputation");
                    repLabelSize = GUI.Font.MeasureString(repLabelText);
                    size.X       = Math.Max(size.X, repLabelSize.X);
                    repBarSize   = new Vector2(Math.Max(0.75f * size.X, 100), repLabelSize.Y);
                    size.X       = Math.Max(size.X, (4.0f / 3.0f) * repBarSize.X);
                    size.Y      += 2 * repLabelSize.Y + 4 + repBarSize.Y;
                    repValueText = ((int)HighlightedLocation.Reputation.Value).ToString();
                }
                GUI.Style.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0].Draw(
                    spriteBatch, new Rectangle((int)(pos.X - 60 * GUI.Scale), (int)(pos.Y - size.Y), (int)(size.X + 120 * GUI.Scale), (int)(size.Y * 2.2f)), Color.Black * hudVisibility);
                var topLeftPos = pos - new Vector2(0.0f, size.Y / 2);
                GUI.DrawString(spriteBatch, topLeftPos, HighlightedLocation.Name, GUI.Style.TextColor * hudVisibility * 1.5f, font: GUI.LargeFont);
                topLeftPos += new Vector2(0.0f, nameSize.Y);
                GUI.DrawString(spriteBatch, topLeftPos, HighlightedLocation.Type.Name, GUI.Style.TextColor * hudVisibility * 1.5f);
                if (showReputation)
                {
                    topLeftPos += new Vector2(0.0f, typeSize.Y + repLabelSize.Y);
                    GUI.DrawString(spriteBatch, topLeftPos, repLabelText, GUI.Style.TextColor * hudVisibility * 1.5f);
                    topLeftPos += new Vector2(0.0f, repLabelSize.Y + 4);
                    Rectangle repBarRect = new Rectangle(new Point((int)topLeftPos.X, (int)topLeftPos.Y), new Point((int)repBarSize.X, (int)repBarSize.Y));
                    RoundSummary.DrawReputationBar(spriteBatch, repBarRect, HighlightedLocation.Reputation.NormalizedValue);
                    GUI.DrawString(spriteBatch, new Vector2(repBarRect.Right + 4, repBarRect.Top), repValueText, GUI.Style.TextColor);
                }
            }
            if (tooltip != null)
            {
                GUIComponent.DrawToolTip(spriteBatch, tooltip.Second, tooltip.First);
            }
            spriteBatch.End();
            GameMain.Instance.GraphicsDevice.ScissorRectangle = prevScissorRect;
            spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
        }
        public void Draw(SpriteBatch spriteBatch, GraphicsDevice graphics, float deltaTime)
        {
            if (GameMain.Config.EnableSplashScreen)
            {
                try
                {
                    DrawSplashScreen(spriteBatch, graphics);
                    if (currSplashScreen != null || PendingSplashScreens.Count > 0)
                    {
                        return;
                    }
                }
                catch (Exception e)
                {
                    DebugConsole.ThrowError("Playing splash screen video failed", e);
                    GameMain.Config.EnableSplashScreen = false;
                }
            }

            var    titleStyle  = GUI.Style?.GetComponentStyle("TitleText");
            Sprite titleSprite = null;

            if (!WaitForLanguageSelection && titleStyle != null && titleStyle.Sprites.ContainsKey(GUIComponent.ComponentState.None))
            {
                titleSprite = titleStyle.Sprites[GUIComponent.ComponentState.None].First()?.Sprite;
            }

            drawn = true;

            currentBackgroundTexture ??= defaultBackgroundTexture;

            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, samplerState: GUI.SamplerState);

            float scale    = (GameMain.GraphicsWidth / (float)currentBackgroundTexture.Width) * 1.2f;
            float paddingX = currentBackgroundTexture.Width * scale - GameMain.GraphicsWidth;
            float paddingY = currentBackgroundTexture.Height * scale - GameMain.GraphicsHeight;

            double  noiseT = (Timing.TotalTime * 0.02f);
            Vector2 pos    = new Vector2((float)PerlinNoise.CalculatePerlin(noiseT, noiseT, 0) - 0.5f, (float)PerlinNoise.CalculatePerlin(noiseT, noiseT, 0.5f) - 0.5f);

            pos = new Vector2(pos.X * paddingX, pos.Y * paddingY);

            spriteBatch.Draw(currentBackgroundTexture,
                             new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2 + pos,
                             null, Color.White, 0.0f, new Vector2(currentBackgroundTexture.Width / 2, currentBackgroundTexture.Height / 2),
                             scale, SpriteEffects.None, 0.0f);

            spriteBatch.Draw(overlay, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), null, Color.White, 0.0f, Vector2.Zero, SpriteEffects.None, 0.0f);

            float noiseStrength = (float)PerlinNoise.CalculatePerlin(noiseT, noiseT, 0);
            float noiseScale    = (float)PerlinNoise.CalculatePerlin(noiseT * 5.0f, noiseT * 2.0f, 0) * 4.0f;

            noiseSprite.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight),
                                  startOffset: new Vector2(Rand.Range(0.0f, noiseSprite.SourceRect.Width), Rand.Range(0.0f, noiseSprite.SourceRect.Height)),
                                  color: Color.White * noiseStrength * 0.1f,
                                  textureScale: Vector2.One * noiseScale);

            titleSprite?.Draw(spriteBatch, new Vector2(GameMain.GraphicsWidth * 0.05f, GameMain.GraphicsHeight * 0.125f),
                              Color.White, origin: new Vector2(0.0f, titleSprite.SourceRect.Height / 2.0f),
                              scale: GameMain.GraphicsHeight / 2000.0f);

            if (WaitForLanguageSelection)
            {
                DrawLanguageSelectionPrompt(spriteBatch, graphics);
            }
            else if (DrawLoadingText)
            {
                if (TextManager.Initialized)
                {
                    string loadText;
                    if (LoadState == 100.0f)
                    {
#if DEBUG
                        if (GameMain.Config.AutomaticQuickStartEnabled || GameMain.Config.AutomaticCampaignLoadEnabled && GameMain.FirstLoad)
                        {
                            loadText = "QUICKSTARTING ...";
                        }
                        else
                        {
#endif
                        loadText = TextManager.Get("PressAnyKey");
#if DEBUG
                    }
#endif
                    }
                    else
                    {
                        loadText = TextManager.Get("Loading");
                        if (LoadState != null)
                        {
                            loadText += " " + (int)LoadState + " %";
                        }
                    }
                    if (GUI.LargeFont != null)
                    {
                        GUI.LargeFont.DrawString(spriteBatch, loadText.ToUpper(),
                                                 new Vector2(GameMain.GraphicsWidth / 2.0f - GUI.LargeFont.MeasureString(loadText.ToUpper()).X / 2.0f, GameMain.GraphicsHeight * 0.75f),
                                                 Color.White);
                    }
                }

                if (GUI.Font != null && selectedTip != null)
                {
                    string   wrappedTip = ToolBox.WrapText(selectedTip, GameMain.GraphicsWidth * 0.5f, GUI.Font);
                    string[] lines      = wrappedTip.Split('\n');
                    float    lineHeight = GUI.Font.MeasureString(selectedTip).Y;

                    for (int i = 0; i < lines.Length; i++)
                    {
                        GUI.Font.DrawString(spriteBatch, lines[i],
                                            new Vector2((int)(GameMain.GraphicsWidth / 2.0f - GUI.Font.MeasureString(lines[i]).X / 2.0f), (int)(GameMain.GraphicsHeight * 0.8f + i * lineHeight)), Color.White);
                    }
                }
            }
            spriteBatch.End();

            spriteBatch.Begin(blendState: BlendState.Additive);

            Vector2 decorativeScale = new Vector2(GameMain.GraphicsHeight / 1080.0f);

            float noiseVal = (float)PerlinNoise.CalculatePerlin(Timing.TotalTime * 0.25f, Timing.TotalTime * 0.5f, 0);
            decorativeGraph.Draw(spriteBatch, (int)(decorativeGraph.FrameCount * noiseVal),
                                 new Vector2(GameMain.GraphicsWidth * 0.001f, GameMain.GraphicsHeight * 0.24f),
                                 Color.White, Vector2.Zero, 0.0f, decorativeScale, SpriteEffects.FlipVertically);

            decorativeMap.Draw(spriteBatch, (int)(decorativeMap.FrameCount * noiseVal),
                               new Vector2(GameMain.GraphicsWidth * 0.99f, GameMain.GraphicsHeight * 0.66f),
                               Color.White, decorativeMap.FrameSize.ToVector2(), 0.0f, decorativeScale);

            if (noiseVal < 0.2f)
            {
                //SCP-CB reference
                randText = (new string[] { "NIL", "black white gray", "Sometimes we would have had time to scream", "e8m106]af", "NO" }).GetRandom();
            }
            else if (noiseVal < 0.3f)
            {
                randText = ToolBox.RandomSeed(9);
            }
            else if (noiseVal < 0.5f)
            {
                randText =
                    Rand.Int(100).ToString().PadLeft(2, '0') + " " +
                    Rand.Int(100).ToString().PadLeft(2, '0') + " " +
                    Rand.Int(100).ToString().PadLeft(2, '0') + " " +
                    Rand.Int(100).ToString().PadLeft(2, '0');
            }

            GUI.LargeFont?.DrawString(spriteBatch, randText,
                                      new Vector2(GameMain.GraphicsWidth - decorativeMap.FrameSize.X * decorativeScale.X * 0.8f, GameMain.GraphicsHeight * 0.57f),
                                      Color.White * (1.0f - noiseVal));

            spriteBatch.End();
        }
        void UpdateDying(float deltaTime)
        {
            if (deathAnimDuration <= 0.0f)
            {
                return;
            }

            float noise        = (PerlinNoise.GetPerlin(WalkPos * 0.002f, WalkPos * 0.003f) - 0.5f) * 5.0f;
            float animStrength = (1.0f - deathAnimTimer / deathAnimDuration);

            Limb baseLimb = GetLimb(LimbType.Head);

            //if head is the main limb, it technically can't be severed - the rest of the limbs are considered severed if the head gets cut off
            if (baseLimb == MainLimb)
            {
                int connectedToHeadCount = GetConnectedLimbs(baseLimb).Count;
                //if there's nothing connected to the head, don't make it wiggle by itself
                if (connectedToHeadCount == 1)
                {
                    baseLimb = null;
                }
                Limb torso = GetLimb(LimbType.Torso, excludeSevered: false);
                if (torso != null)
                {
                    //if there are more limbs connected to the torso than to the head, make the torso wiggle instead
                    int connectedToTorsoCount = GetConnectedLimbs(torso).Count;
                    if (connectedToTorsoCount > connectedToHeadCount)
                    {
                        baseLimb = torso;
                    }
                }
            }
            else if (baseLimb == null)
            {
                baseLimb = GetLimb(LimbType.Torso, excludeSevered: true);
                if (baseLimb == null)
                {
                    return;
                }
            }

            var connectedToBaseLimb = GetConnectedLimbs(baseLimb);

            Limb tail = GetLimb(LimbType.Tail);

            if (baseLimb != null)
            {
                baseLimb.body.ApplyTorque((float)(Math.Sqrt(baseLimb.Mass) * Dir * (Math.Sin(WalkPos) + noise)) * 30.0f * animStrength);
            }
            if (tail != null && connectedToBaseLimb.Contains(tail))
            {
                tail.body.ApplyTorque((float)(Math.Sqrt(tail.Mass) * -Dir * (Math.Sin(WalkPos) + noise)) * 30.0f * animStrength);
            }

            WalkPos += deltaTime * 10.0f * animStrength;

            Vector2 centerOfMass = GetCenterOfMass();

            foreach (Limb limb in Limbs)
            {
                if (!connectedToBaseLimb.Contains(limb))
                {
                    continue;
                }
#if CLIENT
                if (limb.LightSource != null)
                {
                    limb.LightSource.Color = Color.Lerp(limb.InitialLightSourceColor, Color.TransparentBlack, deathAnimTimer / deathAnimDuration);
                    if (limb.InitialLightSpriteAlpha.HasValue)
                    {
                        limb.LightSource.OverrideLightSpriteAlpha = MathHelper.Lerp(limb.InitialLightSpriteAlpha.Value, 0.0f, deathAnimTimer / deathAnimDuration);
                    }
                }
#endif
                if (limb.type == LimbType.Head || limb.type == LimbType.Tail || limb.IsSevered || !limb.body.Enabled)
                {
                    continue;
                }
                if (limb.Mass <= 0.0f)
                {
                    string errorMsg = "Creature death animation error: invalid limb mass on character \"" + character.SpeciesName + "\" (type: " + limb.type + ", mass: " + limb.Mass + ")";
                    DebugConsole.ThrowError(errorMsg);
                    GameAnalyticsManager.AddErrorEventOnce("FishAnimController.UpdateDying:InvalidMass" + character.ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                    deathAnimTimer = deathAnimDuration;
                    return;
                }

                Vector2 diff = (centerOfMass - limb.SimPosition);
                if (!MathUtils.IsValid(diff))
                {
                    string errorMsg = "Creature death animation error: invalid diff (center of mass: " + centerOfMass + ", limb position: " + limb.SimPosition + ")";
                    DebugConsole.ThrowError(errorMsg);
                    GameAnalyticsManager.AddErrorEventOnce("FishAnimController.UpdateDying:InvalidDiff" + character.ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                    deathAnimTimer = deathAnimDuration;
                    return;
                }

                limb.body.ApplyForce(diff * (float)(Math.Sin(WalkPos) * Math.Sqrt(limb.Mass)) * 30.0f * animStrength, maxVelocity: 10.0f);
            }
        }
Esempio n. 5
0
        void UpdateDying(float deltaTime)
        {
            if (deathAnimDuration <= 0.0f)
            {
                return;
            }

            float noise        = (PerlinNoise.GetPerlin(WalkPos * 0.002f, WalkPos * 0.003f) - 0.5f) * 5.0f;
            float animStrength = (1.0f - deathAnimTimer / deathAnimDuration);

            Limb head = GetLimb(LimbType.Head);

            if (head != null && head.IsSevered)
            {
                return;
            }
            Limb tail = GetLimb(LimbType.Tail);

            if (head != null && !head.IsSevered)
            {
                head.body.ApplyTorque((float)(Math.Sqrt(head.Mass) * Dir * (Math.Sin(WalkPos) + noise)) * 30.0f * animStrength);
            }
            if (tail != null && !tail.IsSevered)
            {
                tail.body.ApplyTorque((float)(Math.Sqrt(tail.Mass) * -Dir * (Math.Sin(WalkPos) + noise)) * 30.0f * animStrength);
            }

            WalkPos += deltaTime * 10.0f * animStrength;

            Vector2 centerOfMass = GetCenterOfMass();

            foreach (Limb limb in Limbs)
            {
#if CLIENT
                if (limb.LightSource != null)
                {
                    limb.LightSource.Color = Color.Lerp(limb.InitialLightSourceColor, Color.TransparentBlack, deathAnimTimer / deathAnimDuration);
                }
#endif
                if (limb.type == LimbType.Head || limb.type == LimbType.Tail || limb.IsSevered || !limb.body.Enabled)
                {
                    continue;
                }
                if (limb.Mass <= 0.0f)
                {
                    string errorMsg = "Creature death animation error: invalid limb mass on character \"" + character.SpeciesName + "\" (type: " + limb.type + ", mass: " + limb.Mass + ")";
                    DebugConsole.ThrowError(errorMsg);
                    GameAnalyticsManager.AddErrorEventOnce("FishAnimController.UpdateDying:InvalidMass" + character.ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                    deathAnimTimer = deathAnimDuration;
                    return;
                }

                Vector2 diff = (centerOfMass - limb.SimPosition);
                if (!MathUtils.IsValid(diff))
                {
                    string errorMsg = "Creature death animation error: invalid diff (center of mass: " + centerOfMass + ", limb position: " + limb.SimPosition + ")";
                    DebugConsole.ThrowError(errorMsg);
                    GameAnalyticsManager.AddErrorEventOnce("FishAnimController.UpdateDying:InvalidDiff" + character.ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                    deathAnimTimer = deathAnimDuration;
                    return;
                }

                limb.body.ApplyForce(diff * (float)(Math.Sin(WalkPos) * Math.Sqrt(limb.Mass)) * 30.0f * animStrength, maxVelocity: 10.0f);
            }
        }
Esempio n. 6
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);
        }
Esempio n. 7
0
        partial void GenerateNoiseMapProjSpecific()
        {
            if (noiseTexture == null)
            {
                noiseTexture    = new Texture2D(GameMain.Instance.GraphicsDevice, generationParams.NoiseResolution, generationParams.NoiseResolution);
                rawNoiseTexture = new Texture2D(GameMain.Instance.GraphicsDevice, generationParams.NoiseResolution, generationParams.NoiseResolution);
                rawNoiseSprite  = new Sprite(rawNoiseTexture, null, null);
            }

            Color[] crackTextureData    = new Color[generationParams.NoiseResolution * generationParams.NoiseResolution];
            Color[] noiseTextureData    = new Color[generationParams.NoiseResolution * generationParams.NoiseResolution];
            Color[] rawNoiseTextureData = new Color[generationParams.NoiseResolution * generationParams.NoiseResolution];
            for (int x = 0; x < generationParams.NoiseResolution; x++)
            {
                for (int y = 0; y < generationParams.NoiseResolution; y++)
                {
                    noiseTextureData[x + y * generationParams.NoiseResolution]    = Color.Lerp(Color.Black, Color.Transparent, Noise[x, y]);
                    rawNoiseTextureData[x + y * generationParams.NoiseResolution] = Color.Lerp(Color.Black, Color.White, Rand.Range(0.0f, 1.0f));
                }
            }

            float   mapRadius = size / 2;
            Vector2 mapCenter = Vector2.One * mapRadius;

            foreach (LocationConnection connection in connections)
            {
                float centerDist = Vector2.Distance(connection.CenterPos, mapCenter);

                Vector2 connectionStart  = connection.Locations[0].MapPosition;
                Vector2 connectionEnd    = connection.Locations[1].MapPosition;
                float   connectionLength = Vector2.Distance(connectionStart, connectionEnd);
                int     iterations       = (int)(Math.Sqrt(connectionLength * generationParams.ConnectionIndicatorIterationMultiplier));
                connection.CrackSegments = MathUtils.GenerateJaggedLine(
                    connectionStart, connectionEnd,
                    iterations, connectionLength * generationParams.ConnectionIndicatorDisplacementMultiplier);

                iterations = (int)(Math.Sqrt(connectionLength * generationParams.ConnectionIterationMultiplier));
                var visualCrackSegments = MathUtils.GenerateJaggedLine(
                    connectionStart, connectionEnd,
                    iterations, connectionLength * generationParams.ConnectionDisplacementMultiplier);

                float totalLength = Vector2.Distance(visualCrackSegments[0][0], visualCrackSegments.Last()[1]);
                for (int i = 0; i < visualCrackSegments.Count; i++)
                {
                    Vector2 start = visualCrackSegments[i][0] * (generationParams.NoiseResolution / (float)size);
                    Vector2 end   = visualCrackSegments[i][1] * (generationParams.NoiseResolution / (float)size);

                    float length = Vector2.Distance(start, end);
                    for (float x = 0; x < 1; x += 1.0f / length)
                    {
                        Vector2 pos = Vector2.Lerp(start, end, x);
                        SetNoiseColorOnArea(pos, MathHelper.Clamp((int)(totalLength / 30), 2, 5) + Rand.Range(-1, 1), Color.Transparent);
                    }
                }
            }

            void SetNoiseColorOnArea(Vector2 pos, int dist, Color color)
            {
                for (int x = -dist; x < dist; x++)
                {
                    for (int y = -dist; y < dist; y++)
                    {
                        float d = 1.0f - new Vector2(x, y).Length() / dist;
                        if (d <= 0)
                        {
                            continue;
                        }

                        int xIndex = (int)pos.X + x;
                        if (xIndex < 0 || xIndex >= generationParams.NoiseResolution)
                        {
                            continue;
                        }
                        int yIndex = (int)pos.Y + y;
                        if (yIndex < 0 || yIndex >= generationParams.NoiseResolution)
                        {
                            continue;
                        }

                        float perlin = (float)PerlinNoise.Perlin(
                            xIndex / (float)generationParams.NoiseResolution * 100.0f,
                            yIndex / (float)generationParams.NoiseResolution * 100.0f, 0);

                        byte a = Math.Max(crackTextureData[xIndex + yIndex * generationParams.NoiseResolution].A, (byte)((d * perlin) * 255));

                        crackTextureData[xIndex + yIndex * generationParams.NoiseResolution].A = a;
                    }
                }
            }

            for (int i = 0; i < noiseTextureData.Length; i++)
            {
                float darken    = noiseTextureData[i].A / 255.0f;
                Color pathColor = Color.Lerp(Color.White, Color.Transparent, noiseTextureData[i].A / 255.0f);
                noiseTextureData[i] =
                    Color.Lerp(noiseTextureData[i], pathColor, crackTextureData[i].A / 255.0f * 0.5f);
            }

            noiseTexture.SetData(noiseTextureData);
            rawNoiseTexture.SetData(rawNoiseTextureData);
        }
Esempio n. 8
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) + CenterOffset;

            Rectangle prevScissorRect = GameMain.Instance.GraphicsDevice.ScissorRectangle;

            spriteBatch.End();
            spriteBatch.GraphicsDevice.ScissorRectangle = Rectangle.Intersect(prevScissorRect, rect);
            spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, 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, GUI.Style.Orange, GUI.Style.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.Identifier + " (" + 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.PrimaryMouseButtonClicked() && !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 - 10), (int)size.X + 60, (int)(size.Y + 50 * 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 * size.Y * 0.8f,
                               location.Type.Name, Color.White * hudOpenState * 1.5f);
            }

            spriteBatch.End();
            GameMain.Instance.GraphicsDevice.ScissorRectangle = prevScissorRect;
            spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
        }
Esempio n. 9
0
        public void Update(float deltaTime)
        {
            position += new Vector2(velocity.X, velocity.Y) * deltaTime;
            depth     = MathHelper.Clamp(depth + velocity.Z * deltaTime, Prefab.MinDepth, Prefab.MaxDepth * 10);

            if (Prefab.FlashInterval > 0.0f)
            {
                flashTimer -= deltaTime;
                if (flashTimer > 0.0f)
                {
                    alpha = 0.0f;
                }
                else
                {
                    //value goes from 0 to 1 and back to 0 during the flash
                    alpha = (float)Math.Sin(-flashTimer / Prefab.FlashDuration * MathHelper.Pi) * PerlinNoise.GetPerlin((float)Timing.TotalTime * 0.1f, (float)Timing.TotalTime * 0.2f);
                    if (flashTimer < -Prefab.FlashDuration)
                    {
                        flashTimer = Prefab.FlashInterval;
                    }
                }
            }

            checkWallsTimer -= deltaTime;
            if (checkWallsTimer <= 0.0f && Level.Loaded != null)
            {
                checkWallsTimer = CheckWallsInterval;

                obstacleDiff = Vector2.Zero;
                if (position.Y > Level.Loaded.Size.Y)
                {
                    obstacleDiff = Vector2.UnitY;
                }
                else if (position.Y < 0.0f)
                {
                    obstacleDiff = -Vector2.UnitY;
                }
                else if (position.X < 0.0f)
                {
                    obstacleDiff = Vector2.UnitX;
                }
                else if (position.X > Level.Loaded.Size.X)
                {
                    obstacleDiff = -Vector2.UnitX;
                }
                else
                {
                    var cells = Level.Loaded.GetCells(position, 1);
                    if (cells.Count > 0)
                    {
                        int cellCount = 0;
                        foreach (Voronoi2.VoronoiCell cell in cells)
                        {
                            Vector2 diff = cell.Center - position;
                            if (diff.LengthSquared() > 5000.0f * 5000.0f)
                            {
                                continue;
                            }
                            obstacleDiff += diff;
                            cellCount++;
                        }
                        if (cellCount > 0)
                        {
                            obstacleDiff /= cellCount;
                            obstacleDist  = obstacleDiff.Length();
                            obstacleDiff  = Vector2.Normalize(obstacleDiff);
                        }
                    }
                }
            }

            if (Swarm != null)
            {
                Vector2 midPoint     = Swarm.MidPoint();
                float   midPointDist = Vector2.Distance(SimPosition, midPoint) * 100.0f;
                if (midPointDist > Swarm.MaxDistance)
                {
                    steeringManager.SteeringSeek(midPoint, ((midPointDist / Swarm.MaxDistance) - 1.0f) * Prefab.Speed);
                }
                steeringManager.SteeringManual(deltaTime, Swarm.AvgVelocity() * Swarm.Cohesion);
            }

            if (Prefab.WanderAmount > 0.0f)
            {
                steeringManager.SteeringWander(Prefab.Speed);
            }

            if (obstacleDiff != Vector2.Zero)
            {
                steeringManager.SteeringManual(deltaTime, -obstacleDiff * (1.0f - obstacleDist / 5000.0f) * Prefab.Speed);
            }

            steeringManager.Update(Prefab.Speed);

            if (Prefab.WanderZAmount > 0.0f)
            {
                wanderZPhase += Rand.Range(-Prefab.WanderZAmount, Prefab.WanderZAmount);
                velocity.Z    = (float)Math.Sin(wanderZPhase) * Prefab.Speed;
            }

            velocity = Vector3.Lerp(velocity, new Vector3(Steering.X, Steering.Y, velocity.Z), deltaTime);

            UpdateDeformations(deltaTime);
        }
Esempio n. 10
0
        public void MoveCamera(float deltaTime, bool allowMove = true, bool allowZoom = true, bool?followSub = null)
        {
            prevPosition = position;
            prevZoom     = zoom;

            float moveSpeed = 20.0f / zoom;

            Vector2 moveCam = Vector2.Zero;

            if (TargetPos == Vector2.Zero)
            {
                Vector2 moveInput = Vector2.Zero;
                if (allowMove && !Freeze)
                {
                    if (GUI.KeyboardDispatcher.Subscriber == null)
                    {
                        if (PlayerInput.KeyDown(Keys.LeftShift))
                        {
                            moveSpeed *= 2.0f;
                        }
                        if (PlayerInput.KeyDown(Keys.LeftControl))
                        {
                            moveSpeed *= 0.5f;
                        }

                        if (GameMain.Config.KeyBind(InputType.Left).IsDown())
                        {
                            moveInput.X -= 1.0f;
                        }
                        if (GameMain.Config.KeyBind(InputType.Right).IsDown())
                        {
                            moveInput.X += 1.0f;
                        }
                        if (GameMain.Config.KeyBind(InputType.Down).IsDown())
                        {
                            moveInput.Y -= 1.0f;
                        }
                        if (GameMain.Config.KeyBind(InputType.Up).IsDown())
                        {
                            moveInput.Y += 1.0f;
                        }
                    }

                    velocity = Vector2.Lerp(velocity, moveInput, deltaTime * 10.0f);
                    moveCam  = velocity * moveSpeed * deltaTime * FreeCamMoveSpeed * 60.0f;

                    if (Screen.Selected == GameMain.GameScreen && (followSub ?? FollowSub))
                    {
                        var closestSub = Submarine.FindClosest(WorldViewCenter);
                        if (closestSub != null)
                        {
                            moveCam += FarseerPhysics.ConvertUnits.ToDisplayUnits(closestSub.Velocity * deltaTime);
                        }
                    }
                }

                if (allowZoom)
                {
                    Vector2 mouseInWorld = ScreenToWorld(PlayerInput.MousePosition);
                    Vector2 diffViewCenter;
                    diffViewCenter = (mouseInWorld - Position) * Zoom;
                    targetZoom     = MathHelper.Clamp(
                        targetZoom + PlayerInput.ScrollWheelSpeed / 1000.0f * zoom,
                        GameMain.DebugDraw ? MinZoom * 0.1f : MinZoom,
                        MaxZoom);

                    if (PlayerInput.KeyDown(Keys.LeftControl))
                    {
                        Zoom += (targetZoom - zoom) / (ZoomSmoothness * 10.0f);
                    }
                    else
                    {
                        Zoom = MathHelper.Lerp(Zoom, targetZoom, deltaTime * 10.0f);
                    }
                    if (!PlayerInput.KeyDown(Keys.F))
                    {
                        Position = mouseInWorld - (diffViewCenter / Zoom);
                    }
                }
            }
            else if (allowMove)
            {
                Vector2 mousePos = PlayerInput.MousePosition;
                Vector2 offset   = mousePos - Resolution.ToVector2() / 2;
                offset.X = offset.X / (Resolution.X * 0.4f);
                offset.Y = -offset.Y / (Resolution.Y * 0.3f);
                if (offset.LengthSquared() > 1.0f)
                {
                    offset.Normalize();
                }
                float offsetUnscaledLen = offset.Length();
                offset *= OffsetAmount;
                // Freeze the camera movement by default, when the cursor is on top of an ui element.
                // Setting a positive value to the OffsetAmount, will override this behaviour.
                if (GUI.MouseOn != null && OffsetAmount > 0)
                {
                    Freeze = true;
                }
                if (CharacterHealth.OpenHealthWindow != null || CrewManager.IsCommandInterfaceOpen || ConversationAction.IsDialogOpen)
                {
                    offset *= 0;
                    Freeze  = false;
                }
                if (Freeze)
                {
                    if (offset.LengthSquared() > 0.001f)
                    {
                        offset = previousOffset;
                    }
                }
                else
                {
                    previousOffset = offset;
                }

                if (allowZoom)
                {
                    //how much to zoom out (zoom completely out when offset is 1000)
                    float zoomOutAmount = GetZoomAmount(offset);
                    //scaled zoom amount
                    float scaledZoom = MathHelper.Lerp(DefaultZoom, MinZoom, zoomOutAmount) * globalZoomScale;
                    //zoom in further if zoomOutAmount is low and resolution is lower than reference
                    float newZoom = scaledZoom * (MathHelper.Lerp(0.3f * (1f - Math.Min(globalZoomScale, 1f)), 0f,
                                                                  (GameMain.Config == null || GameMain.Config.EnableMouseLook) ? (float)Math.Sqrt(offsetUnscaledLen) : 0.3f) + 1f);

                    Zoom += (newZoom - zoom) / ZoomSmoothness;
                }

                //force targetzoom to the current zoom value, so the camera stays at the same zoom when switching to freecam
                targetZoom = Zoom;

                Vector2 diff = (TargetPos + offset) - position;

                moveCam = diff / MoveSmoothness;
            }
            rotation        += angularVelocity * deltaTime;
            angularVelocity *= (1.0f - angularDamping);
            angularVelocity += -rotation * angularSpring;

            angularDamping = 0.05f;
            angularSpring  = 0.2f;

            if (Shake < 0.01f)
            {
                shakePosition = Vector2.Zero;
                shakeTimer    = 0.0f;
            }
            else
            {
                shakeTimer += deltaTime * 5.0f;
                Vector2 noisePos = new Vector2((float)PerlinNoise.CalculatePerlin(shakeTimer, shakeTimer, 0) - 0.5f, (float)PerlinNoise.CalculatePerlin(shakeTimer, shakeTimer, 0.5f) - 0.5f);

                shakePosition = noisePos * Shake * 2.0f;
                Shake         = MathHelper.Lerp(Shake, 0.0f, deltaTime * 2.0f);
            }

            Translate(moveCam + shakePosition);
            Freeze = false;
        }