diff --git a/Engines/FlatRedBallXNA/FlatRedBall/Entities/CameraControllingEntity.cs b/Engines/FlatRedBallXNA/FlatRedBall/Entities/CameraControllingEntity.cs index 0c0fc2bcc..92f1ec3e5 100644 --- a/Engines/FlatRedBallXNA/FlatRedBall/Entities/CameraControllingEntity.cs +++ b/Engines/FlatRedBallXNA/FlatRedBall/Entities/CameraControllingEntity.cs @@ -16,8 +16,18 @@ public enum CameraBehaviorType public enum TargetApproachStyle { + /// + /// The camera moves to the target position immediately, effectively locking on to its position. + /// Immediate, + /// + /// The camera moves to the target position smoothly, but not at a constant speed. The camera will move faster + /// if it is further away from the target, and slower if it is closer. + /// Smooth, + /// + /// The camera moves to the target at a constant speed, regardless of the distance between the camera and the target. + /// ConstantSpeed } @@ -36,6 +46,7 @@ public class CameraControllingEntity : PositionedObject private float minZoomPercent; private bool isAutoZoomEnabled; private float furthestZoom; + private AxisAlignedRectangle MaximumViewRectangle = new AxisAlignedRectangle(); /// @@ -123,6 +134,9 @@ public bool LerpSmooth } } + /// + /// The type of approach to use when moving the camera to the target position. + /// public TargetApproachStyle TargetApproachStyle { get; set; } = TargetApproachStyle.Smooth; /// @@ -169,6 +183,7 @@ public float MaxViewableAreaMultiplier /// public float MaxViewableAreaHeight => defaultOrthoHeight * MaxViewableAreaMultiplier; + public bool IsKeepingTargetsInView { get; set; } = false; /// /// The amount of smoothing. The larger the number, faster the Camera moves. This value is ignored if TargetApproachStyle is Immediate. @@ -292,12 +307,18 @@ public void Activity() windowVisualization.Height = ScrollingWindowHeight; } + if (IsKeepingTargetsInView && hasActivityBeenCalled) + { + KeepTargetsInView(); + } + // Zoom should be happening first, and then targeting: if (isAutoZoomEnabled) { ApplyZoom(); } + var target = GetTarget(); var effectiveTargetApproachStyleX = @@ -347,6 +368,40 @@ public void Activity() hasActivityBeenCalled = true; } + private void KeepTargetsInView() + { + MaximumViewRectangle.Position = this.Position.AtZ(0); + MaximumViewRectangle.Width = MaxViewableAreaWidth; + MaximumViewRectangle.Height = MaxViewableAreaHeight; + + + for (int i = 0; i < Targets.Count; i++) + { + var target = Targets[i] as PositionedObject; + + if(target != null) + { + if(target.Y > MaximumViewRectangle.Y + MaximumViewRectangle.Height / 2) + { + target.Y = MaximumViewRectangle.Y + MaximumViewRectangle.Height / 2; + } + else if(target.Y < MaximumViewRectangle.Y - MaximumViewRectangle.Height / 2) + { + target.Y = MaximumViewRectangle.Y - MaximumViewRectangle.Height / 2; + } + + if(target.X > MaximumViewRectangle.X + MaximumViewRectangle.Width / 2) + { + target.X = MaximumViewRectangle.X + MaximumViewRectangle.Width / 2; + } + else if(target.X < MaximumViewRectangle.X - MaximumViewRectangle.Width / 2) + { + target.X = MaximumViewRectangle.X - MaximumViewRectangle.Width / 2; + } + } + } + } + private void ApplyZoom() { var separationVector = GetTargetSeparation();