237 lines
5.6 KiB
C#
237 lines
5.6 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using Godot;
|
|
using Godot.Bridge;
|
|
using Godot.NativeInterop;
|
|
|
|
[ScriptPath("res://Scripts/CameraController.cs")]
|
|
public partial class CameraController : Node2D
|
|
{
|
|
public Node2D follow;
|
|
|
|
public float scrollSpeed = 5f;
|
|
|
|
public float shakeTime;
|
|
|
|
public float shakeIntensity = 2f;
|
|
|
|
public Vector2? target;
|
|
|
|
private Vector2? endShake;
|
|
|
|
[Export(PropertyHint.None, "")]
|
|
public Vector2 offset = defaultOffset;
|
|
|
|
public float speed = 1f;
|
|
|
|
public static CameraController instance;
|
|
|
|
[Export(PropertyHint.None, "")]
|
|
public Control contents;
|
|
|
|
public static Coroutine transitionRoutine;
|
|
|
|
[Export(PropertyHint.None, "")]
|
|
public Control cover;
|
|
|
|
public static readonly Vector2 defaultOffset = new Vector2(0f, -16f);
|
|
|
|
public const float defaultShake = 2f;
|
|
|
|
public override void _EnterTree()
|
|
{
|
|
base.ProcessPriority = int.MaxValue;
|
|
instance = this;
|
|
}
|
|
|
|
public static void Shake(float time = 5f, float intensity = 1f)
|
|
{
|
|
instance.shakeTime = time;
|
|
instance.shakeIntensity = intensity;
|
|
}
|
|
|
|
public override void _PhysicsProcess(double delta)
|
|
{
|
|
if (follow != null)
|
|
{
|
|
base.GlobalPosition = base.GlobalPosition.Lerp(follow.GlobalPosition + offset, speed * Main.physisDelta);
|
|
}
|
|
else if (target.HasValue)
|
|
{
|
|
base.GlobalPosition = base.GlobalPosition.Lerp(target.Value, speed * Main.physisDelta);
|
|
}
|
|
if (Room.current != null)
|
|
{
|
|
base.GlobalPosition = new Vector2(Mathf.Clamp(base.GlobalPosition.X, Room.current.cameraLimit[0].X, Room.current.cameraLimit[1].X), Mathf.Clamp(base.GlobalPosition.Y, Room.current.cameraLimit[0].Y, Room.current.cameraLimit[1].Y));
|
|
}
|
|
DoShake();
|
|
if (shakeTime > 0f)
|
|
{
|
|
shakeTime -= Main.physisDelta;
|
|
}
|
|
CallDeferred(MethodName.LateUpdate);
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
}
|
|
|
|
private void DoShake()
|
|
{
|
|
if (shakeTime > 0f)
|
|
{
|
|
if (!target.HasValue && follow == null)
|
|
{
|
|
Vector2 valueOrDefault = endShake.GetValueOrDefault();
|
|
if (!endShake.HasValue)
|
|
{
|
|
valueOrDefault = base.GlobalPosition;
|
|
endShake = valueOrDefault;
|
|
}
|
|
}
|
|
float[] array = new float[2]
|
|
{
|
|
Main.RandomRange(0f - shakeIntensity, shakeIntensity),
|
|
Main.RandomRange(0f - shakeIntensity, shakeIntensity)
|
|
};
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
if (array[i] > -1f && array[i] < 1f)
|
|
{
|
|
if (array[i] > 0f)
|
|
{
|
|
array[i] = 1f;
|
|
}
|
|
else
|
|
{
|
|
array[1] = -1f;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
array[i] = Mathf.Round(array[i]);
|
|
}
|
|
}
|
|
Vector2 vector = new Vector2(array[0], array[1]);
|
|
contents.Position = vector;
|
|
if (!endShake.HasValue)
|
|
{
|
|
base.GlobalPosition -= vector;
|
|
}
|
|
else
|
|
{
|
|
base.GlobalPosition = endShake.Value + vector;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!target.HasValue && follow == null && endShake.HasValue)
|
|
{
|
|
base.GlobalPosition = endShake.Value;
|
|
}
|
|
endShake = null;
|
|
contents.Position = Vector2.Zero;
|
|
}
|
|
}
|
|
|
|
public static void Transition(Color color, float time = 0f, int? sort = null, Color? startColor = null)
|
|
{
|
|
if (sort.HasValue)
|
|
{
|
|
instance.cover.ZIndex = sort.Value;
|
|
}
|
|
else
|
|
{
|
|
instance.cover.ZIndex = 4000;
|
|
}
|
|
instance.cover.Visible = true;
|
|
if (time == 0f)
|
|
{
|
|
instance.cover.SelfModulate = color;
|
|
return;
|
|
}
|
|
instance.cover.SelfModulate = (startColor.HasValue ? startColor.Value : instance.cover.SelfModulate);
|
|
Coroutine coroutine = transitionRoutine;
|
|
if (coroutine != null && !coroutine.done)
|
|
{
|
|
Coroutine.Stop(transitionRoutine);
|
|
}
|
|
transitionRoutine = Coroutine.Start(DelayedTransition(color, time, instance.cover.SelfModulate));
|
|
}
|
|
|
|
private static IEnumerator DelayedTransition(Color to, float time, Color start)
|
|
{
|
|
for (float a = 0f; a <= time; a += Main.deltaTime)
|
|
{
|
|
instance.cover.SelfModulate = start.Lerp(to, a / time);
|
|
yield return null;
|
|
}
|
|
instance.cover.SelfModulate = to;
|
|
}
|
|
|
|
public static IEnumerator PanToObj(Node2D targetObj, float time = 1f, bool fixedRate = true, bool addOffset = true, bool setTarget = true)
|
|
{
|
|
Coroutine c = Coroutine.Start(PanToObj(instance.GlobalPosition, targetObj, time, fixedRate, addOffset, setTarget));
|
|
while (!c.done)
|
|
{
|
|
yield return null;
|
|
}
|
|
}
|
|
|
|
public static IEnumerator PanToObj(Vector2 startPos, Node2D targetObj, float time = 1f, bool fixedRate = true, bool addOffset = true, bool setTarget = true)
|
|
{
|
|
Coroutine routine = Coroutine.Start(Pan(startPos, targetObj.GlobalPosition + (addOffset ? instance.offset : Vector2.Zero), time, fixedRate));
|
|
while (!routine.done)
|
|
{
|
|
yield return null;
|
|
}
|
|
if (setTarget)
|
|
{
|
|
instance.follow = targetObj;
|
|
}
|
|
}
|
|
|
|
public static IEnumerator Pan(Vector2 pos, float time, bool fixedRate = true, float failsafe = 400f)
|
|
{
|
|
Coroutine c = Coroutine.Start(Pan(instance.GlobalPosition, pos, time, fixedRate, failsafe));
|
|
while (!c.done)
|
|
{
|
|
yield return null;
|
|
}
|
|
}
|
|
|
|
public static IEnumerator Pan(Vector2 startPos, Vector2 pos, float time, bool fixedRate = true, float failsafe = 400f)
|
|
{
|
|
instance.follow = null;
|
|
if (fixedRate)
|
|
{
|
|
while (failsafe > 0f)
|
|
{
|
|
float num = instance.GlobalPosition.DistanceSquaredTo(pos);
|
|
if (!(num > 1.1f))
|
|
{
|
|
break;
|
|
}
|
|
instance.GlobalPosition += instance.GlobalPosition.DirectionTo(pos).Snapped(Vector2.One) * time * Mathf.Clamp(num / 3f, 0f, 1f);
|
|
failsafe -= Main.deltaTime;
|
|
yield return null;
|
|
}
|
|
if (failsafe <= 0f)
|
|
{
|
|
instance.GlobalPosition = pos;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (float a = 0f; a < time; a += Main.deltaTime)
|
|
{
|
|
instance.GlobalPosition = startPos.Lerp(pos, a / time);
|
|
yield return null;
|
|
}
|
|
}
|
|
instance.GlobalPosition = new Vector2(Mathf.Round(pos.X), Mathf.Round(pos.Y));
|
|
}
|
|
|
|
}
|