diff --git a/scene/Room.tscn b/scene/Room.tscn index 4ad88d5..4e72eca 100644 --- a/scene/Room.tscn +++ b/scene/Room.tscn @@ -1,9 +1,10 @@ -[gd_scene load_steps=5 format=2] +[gd_scene load_steps=6 format=2] [ext_resource path="res://prefab/role/Player.tscn" type="PackedScene" id=1] [ext_resource path="res://resource/map/dungeon_test.tmx" type="PackedScene" id=2] [ext_resource path="res://src/room/RoomManager.cs" type="Script" id=3] [ext_resource path="res://prefab/ui/Cursor.tscn" type="PackedScene" id=4] +[ext_resource path="res://src/camera/MainCamera.cs" type="Script" id=5] [node name="Room" type="Node2D"] script = ExtResource( 3 ) @@ -21,6 +22,7 @@ process_mode = 0 smoothing_enabled = true smoothing_speed = 8.0 +script = ExtResource( 5 ) [node name="ObjectRoot" type="Node2D" parent="."] diff --git a/src/camera/MainCamera.cs b/src/camera/MainCamera.cs new file mode 100644 index 0000000..a1fa3cd --- /dev/null +++ b/src/camera/MainCamera.cs @@ -0,0 +1,87 @@ +using System.Collections.Generic; +using Godot; + +public class MainCamera : Camera2D +{ + //当前场景的相机对象 + public static MainCamera CurrentCamera { get; private set; } + + //抖动力度(px) + [Export] public Vector2 ShakeDistance = Vector2.Zero; + //恢复系数 + [Export] public float RecoveryCoefficient = 100f; + //抖动开关 + public bool Enable = true; + + private long _index = 0; + private Vector2 _prossesDistance = Vector2.Zero; + private readonly Dictionary _shakeMap = new Dictionary(); + + public override void _Ready() + { + CurrentCamera = this; + } + public override void _PhysicsProcess(float delta) + { + _Shake(delta); + } + + //抖动调用 + private void _Shake(float delta) + { + if (Enable) + { + var _distance = _CalculateDistance(); + Offset += new Vector2( + (float)GD.RandRange(-_distance.x, _distance.x) - Offset.x, + (float)GD.RandRange(-_distance.y, _distance.y) - Offset.y + ); + _prossesDistance = Vector2.Zero; + } + else + { + Offset = Offset.LinearInterpolate(Vector2.Zero, RecoveryCoefficient * delta); + } + } + + //计算相机需要抖动的值 + private Vector2 _CalculateDistance() + { + Vector2 temp = Vector2.Zero; + float length = 0; + foreach (var item in _shakeMap) + { + var value = item.Value; + float tempLenght = value.Length(); + if (tempLenght > length) + { + length = tempLenght; + temp = value; + } + } + return _prossesDistance.Length() > length ? _prossesDistance : temp; + } + + //设置帧抖动, 结束后自动清零, 需要每一帧调用 + public void ProssesShakeDistance(Vector2 value) + { + if (value.Length() > _prossesDistance.Length()) + { + _prossesDistance = value; + } + } + + //创建一个抖动, 并设置抖动时间 + public async void CreateShake(Vector2 value, float time) + { + if (time > 0) + { + long tempIndex = _index++; + SceneTreeTimer sceneTreeTimer = GetTree().CreateTimer(time); + _shakeMap[tempIndex] = value; + await ToSignal(sceneTreeTimer, "timeout"); + _shakeMap.Remove(tempIndex); + } + } + +}