相机功能beta版本
This commit is contained in:
parent
26b30eb032
commit
b8373aed65
|
|
@ -1,9 +1,10 @@
|
||||||
[gd_scene load_steps=5 format=3 uid="uid://cw6buluknvjj"]
|
[gd_scene load_steps=6 format=3 uid="uid://cw6buluknvjj"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://djk7tg2puphgv" path="res://_camera/camera_test.gd" id="1_05blt"]
|
[ext_resource type="Script" uid="uid://djk7tg2puphgv" path="res://_camera/camera_test.gd" id="1_05blt"]
|
||||||
[ext_resource type="Script" uid="uid://py4h5jxlncro" path="res://addons/reedcamera/scripts/CameraPointer.gd" id="1_e7rkk"]
|
[ext_resource type="Script" uid="uid://py4h5jxlncro" path="res://addons/reedcamera/scripts/CameraPointer.gd" id="1_e7rkk"]
|
||||||
[ext_resource type="Script" uid="uid://dwr1s51svvank" path="res://addons/reedcamera/scripts/camera_tools/CameraShakeController.gd" id="2_rbequ"]
|
[ext_resource type="Script" uid="uid://dwr1s51svvank" path="res://addons/reedcamera/scripts/camera_tools/CameraShakeController.gd" id="2_rbequ"]
|
||||||
[ext_resource type="Script" uid="uid://bhl5it46hv4n2" path="res://addons/reedcamera/scripts/camera_tools/CameraAnchorController.gd" id="4_877nu"]
|
[ext_resource type="Script" uid="uid://bhl5it46hv4n2" path="res://addons/reedcamera/scripts/camera_tools/CameraAnchorController.gd" id="4_877nu"]
|
||||||
|
[ext_resource type="Script" uid="uid://wl83yn33gu3m" path="res://addons/reedcamera/scripts/camera_tools/CameraFollowController.gd" id="5_kdnmf"]
|
||||||
|
|
||||||
[node name="PlateformerCamera" type="Camera2D"]
|
[node name="PlateformerCamera" type="Camera2D"]
|
||||||
script = ExtResource("1_05blt")
|
script = ExtResource("1_05blt")
|
||||||
|
|
@ -22,3 +23,8 @@ script = ExtResource("4_877nu")
|
||||||
affect_position = true
|
affect_position = true
|
||||||
affect_zoom = true
|
affect_zoom = true
|
||||||
metadata/_custom_type_script = "uid://bhl5it46hv4n2"
|
metadata/_custom_type_script = "uid://bhl5it46hv4n2"
|
||||||
|
|
||||||
|
[node name="ReedCameraFollowController" type="Node" parent="CameraPointer"]
|
||||||
|
script = ExtResource("5_kdnmf")
|
||||||
|
affect_position = true
|
||||||
|
metadata/_custom_type_script = "uid://wl83yn33gu3m"
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,6 @@ func _draw() -> void:
|
||||||
func _process(delta: float) -> void:
|
func _process(delta: float) -> void:
|
||||||
queue_redraw()
|
queue_redraw()
|
||||||
|
|
||||||
|
|
||||||
func set_move_input(dir: Vector2) -> void:
|
func set_move_input(dir: Vector2) -> void:
|
||||||
m_input_intent_direction = dir
|
m_input_intent_direction = dir
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,6 @@ script = ExtResource("10_g4f48")
|
||||||
|
|
||||||
[node name="CameraAnchor" parent="Props" instance=ExtResource("11_o5yb1")]
|
[node name="CameraAnchor" parent="Props" instance=ExtResource("11_o5yb1")]
|
||||||
position = Vector2(-39, 1203)
|
position = Vector2(-39, 1203)
|
||||||
zoom = Vector2(0.75, 0.75)
|
|
||||||
|
|
||||||
[node name="[Prop_0000]" type="Node" parent="Props/CameraAnchor"]
|
[node name="[Prop_0000]" type="Node" parent="Props/CameraAnchor"]
|
||||||
script = ExtResource("12_vhd7q")
|
script = ExtResource("12_vhd7q")
|
||||||
|
|
|
||||||
|
|
@ -134,8 +134,7 @@ init_act_id = 0
|
||||||
script = ExtResource("7_8ou3l")
|
script = ExtResource("7_8ou3l")
|
||||||
|
|
||||||
[node name="CameraAnchor" parent="Props" instance=ExtResource("8_dq7pn")]
|
[node name="CameraAnchor" parent="Props" instance=ExtResource("8_dq7pn")]
|
||||||
position = Vector2(540, -400)
|
position = Vector2(336, -385)
|
||||||
zoom = Vector2(0.75, 0.75)
|
|
||||||
limit_top = -335
|
limit_top = -335
|
||||||
limit_bottom = 240
|
limit_bottom = 240
|
||||||
limit_left = -427
|
limit_left = -427
|
||||||
|
|
@ -159,10 +158,10 @@ state_id = 1
|
||||||
effects = Array[ExtResource("12_fmhh5")]([ExtResource("14_nnp13")])
|
effects = Array[ExtResource("12_fmhh5")]([ExtResource("14_nnp13")])
|
||||||
|
|
||||||
[node name="PlayerTriggerVolumn" parent="Props" instance=ExtResource("15_lg3ok")]
|
[node name="PlayerTriggerVolumn" parent="Props" instance=ExtResource("15_lg3ok")]
|
||||||
visible = false
|
|
||||||
position = Vector2(560, -480)
|
position = Vector2(560, -480)
|
||||||
|
|
||||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Props/PlayerTriggerVolumn"]
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="Props/PlayerTriggerVolumn"]
|
||||||
|
visible = false
|
||||||
show_behind_parent = true
|
show_behind_parent = true
|
||||||
position = Vector2(-25.5, -2)
|
position = Vector2(-25.5, -2)
|
||||||
shape = SubResource("RectangleShape2D_oupin")
|
shape = SubResource("RectangleShape2D_oupin")
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
[gd_resource type="Resource" script_class="SceneTrigger" load_steps=16 format=3 uid="uid://bym4pb0ellj7b"]
|
[gd_resource type="Resource" script_class="SceneTrigger" load_steps=20 format=3 uid="uid://bym4pb0ellj7b"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://baamspwt4rm4r" path="res://addons/reedscene/scene/guard.gd" id="1_ebfhi"]
|
[ext_resource type="Script" uid="uid://baamspwt4rm4r" path="res://addons/reedscene/scene/guard.gd" id="1_ebfhi"]
|
||||||
[ext_resource type="Script" uid="uid://ons77en82uls" path="res://addons/reedscene/scene/scene_trigger/base/SceneTrigger.gd" id="2_cq8o1"]
|
[ext_resource type="Script" uid="uid://ons77en82uls" path="res://addons/reedscene/scene/scene_trigger/base/SceneTrigger.gd" id="2_cq8o1"]
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
[ext_resource type="Script" uid="uid://bjstkg23cq6vq" path="res://addons/reedscene/scene/scene_trigger/STE_SwitchAct.gd" id="5_m44nk"]
|
[ext_resource type="Script" uid="uid://bjstkg23cq6vq" path="res://addons/reedscene/scene/scene_trigger/STE_SwitchAct.gd" id="5_m44nk"]
|
||||||
[ext_resource type="Script" uid="uid://c8qq8400vebpg" path="res://addons/reedscene/scene/scene_trigger/STT_Self.gd" id="6_qb8kc"]
|
[ext_resource type="Script" uid="uid://c8qq8400vebpg" path="res://addons/reedscene/scene/scene_trigger/STT_Self.gd" id="6_qb8kc"]
|
||||||
[ext_resource type="Script" uid="uid://dcn3k2vc6on0c" path="res://addons/reedscene/scene/scene_trigger/STT_Tree.gd" id="7_547il"]
|
[ext_resource type="Script" uid="uid://dcn3k2vc6on0c" path="res://addons/reedscene/scene/scene_trigger/STT_Tree.gd" id="7_547il"]
|
||||||
|
[ext_resource type="Script" uid="uid://cwxwsfl1mx7kc" path="res://addons/reedscene/scene/scene_trigger/STT_Autoload.gd" id="8_cq8o1"]
|
||||||
[ext_resource type="Script" uid="uid://cdprpen0jyr6d" path="res://addons/reedscene/scene/scene_trigger/STR_NodePath.gd" id="8_kur88"]
|
[ext_resource type="Script" uid="uid://cdprpen0jyr6d" path="res://addons/reedscene/scene/scene_trigger/STR_NodePath.gd" id="8_kur88"]
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_yc616"]
|
[sub_resource type="Resource" id="Resource_yc616"]
|
||||||
|
|
@ -41,6 +42,22 @@ target = SubResource("Resource_kdh4c")
|
||||||
effect = Array[ExtResource("4_g7ixm")]([SubResource("Resource_jd40h")])
|
effect = Array[ExtResource("4_g7ixm")]([SubResource("Resource_jd40h")])
|
||||||
metadata/_custom_type_script = "uid://dxj5vimigc651"
|
metadata/_custom_type_script = "uid://dxj5vimigc651"
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_cq8o1"]
|
||||||
|
script = ExtResource("5_m44nk")
|
||||||
|
func_name = &"player_follow_camera"
|
||||||
|
metadata/_custom_type_script = "uid://bjstkg23cq6vq"
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_m0qh3"]
|
||||||
|
script = ExtResource("8_cq8o1")
|
||||||
|
autoload_name = &"GlobalEvent"
|
||||||
|
metadata/_custom_type_script = "uid://cwxwsfl1mx7kc"
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_g7ixm"]
|
||||||
|
script = ExtResource("3_m0qh3")
|
||||||
|
target = SubResource("Resource_m0qh3")
|
||||||
|
effect = Array[ExtResource("4_g7ixm")]([SubResource("Resource_cq8o1")])
|
||||||
|
metadata/_custom_type_script = "uid://dxj5vimigc651"
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_8u4ru"]
|
[sub_resource type="Resource" id="Resource_8u4ru"]
|
||||||
script = ExtResource("8_kur88")
|
script = ExtResource("8_kur88")
|
||||||
node_path = NodePath("../Props/PlayerTriggerVolumn")
|
node_path = NodePath("../Props/PlayerTriggerVolumn")
|
||||||
|
|
@ -50,5 +67,5 @@ metadata/_custom_type_script = "uid://cdprpen0jyr6d"
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("2_cq8o1")
|
script = ExtResource("2_cq8o1")
|
||||||
trigger_register_conifg = SubResource("Resource_8u4ru")
|
trigger_register_conifg = SubResource("Resource_8u4ru")
|
||||||
trigger_effect_pairs = Array[ExtResource("3_m0qh3")]([SubResource("Resource_vv5v7"), SubResource("Resource_ig5jt")])
|
trigger_effect_pairs = Array[ExtResource("3_m0qh3")]([SubResource("Resource_vv5v7"), SubResource("Resource_ig5jt"), SubResource("Resource_g7ixm")])
|
||||||
metadata/_custom_type_script = "uid://ons77en82uls"
|
metadata/_custom_type_script = "uid://ons77en82uls"
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ signal player_dead(player: Player)
|
||||||
var _cached_player_controller: PlayerController
|
var _cached_player_controller: PlayerController
|
||||||
var _cached_player: Player
|
var _cached_player: Player
|
||||||
|
|
||||||
|
var _camera_follower : Node = null
|
||||||
|
|
||||||
## player controller進入tree會注冊自己到Global
|
## player controller進入tree會注冊自己到Global
|
||||||
func register_player_controller(pc: PlayerController) -> PlayerController:
|
func register_player_controller(pc: PlayerController) -> PlayerController:
|
||||||
if not pc: return null
|
if not pc: return null
|
||||||
|
|
@ -18,6 +20,10 @@ func register_player(player: Player) -> Player:
|
||||||
if not player: return null
|
if not player: return null
|
||||||
|
|
||||||
_cached_player = player
|
_cached_player = player
|
||||||
|
|
||||||
|
##如果我们缓存了一个camera_follower,在玩家重生的时候我们会让follower自动绑定
|
||||||
|
if _camera_follower:
|
||||||
|
_camera_follower.register_follower(_cached_player)
|
||||||
return _cached_player
|
return _cached_player
|
||||||
|
|
||||||
## 外部快速获取Player
|
## 外部快速获取Player
|
||||||
|
|
@ -28,6 +34,28 @@ func get_player() -> Player:
|
||||||
func get_player_controller() -> PlayerController:
|
func get_player_controller() -> PlayerController:
|
||||||
return _cached_player_controller
|
return _cached_player_controller
|
||||||
|
|
||||||
|
func player_follow_camera() -> void:
|
||||||
|
if not _cached_player:return
|
||||||
|
|
||||||
|
var cam := ReedCameraSystem.get_current_camera_pointer() as CameraPointer
|
||||||
|
if not cam:return
|
||||||
|
|
||||||
|
var follower := cam.get_tool_by_type(CameraPointer.ToolType.FOLLOWER)
|
||||||
|
if not follower:return
|
||||||
|
|
||||||
|
follower.register_follower(_cached_player)
|
||||||
|
_camera_follower = follower
|
||||||
|
|
||||||
|
func player_unfollow_camera() -> void:
|
||||||
|
var cam := ReedCameraSystem.get_current_camera_pointer() as CameraPointer
|
||||||
|
if not cam:return
|
||||||
|
|
||||||
|
var follower := cam.get_tool_by_type(CameraPointer.ToolType.FOLLOWER)
|
||||||
|
if not follower:return
|
||||||
|
|
||||||
|
follower.unregister_follower()
|
||||||
|
_camera_follower = null
|
||||||
|
|
||||||
## 外部用于监听Player死亡
|
## 外部用于监听Player死亡
|
||||||
func boradcast_player_dead_event(player:Player) -> void:
|
func boradcast_player_dead_event(player:Player) -> void:
|
||||||
player_dead.emit(player)
|
player_dead.emit(player)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,10 @@ const CAMERA_SYSTEM_NAME : StringName = "ReedCameraSystem"
|
||||||
const CAMERA_ANCHOR_NAME : StringName = "CameraAnchor"
|
const CAMERA_ANCHOR_NAME : StringName = "CameraAnchor"
|
||||||
const CAMERA_FOLLOWER_NAME : StringName = "CameraFollower"
|
const CAMERA_FOLLOWER_NAME : StringName = "CameraFollower"
|
||||||
|
|
||||||
|
const CAMERA_TOOL_SHAKER : String = "res://addons/reedcamera/scripts/camera_tools/CameraShakeController.gd"
|
||||||
|
const CAMERA_TOOL_ANCHOR : String = "res://addons/reedcamera/scripts/camera_tools/CameraAnchorController.gd"
|
||||||
|
const CAMERA_TOOL_FOLLOWER : String = "res://addons/reedcamera/scripts/camera_tools/CameraFollowController.gd"
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region GroupName
|
#region GroupName
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,20 @@ class_name CameraPointer
|
||||||
|
|
||||||
const _CONSTANTS := preload("res://addons/reedcamera/_data/CameraSystemConst.gd")
|
const _CONSTANTS := preload("res://addons/reedcamera/_data/CameraSystemConst.gd")
|
||||||
|
|
||||||
|
## 相机指针所能持有的工具种类
|
||||||
|
enum ToolType{
|
||||||
|
SHAKER,
|
||||||
|
ANCHOR,
|
||||||
|
FOLLOWER
|
||||||
|
}
|
||||||
|
|
||||||
|
## 相机工具和脚本的映射
|
||||||
|
const type_script_map:Dictionary = {
|
||||||
|
ToolType.SHAKER : preload("res://addons/reedcamera/scripts/camera_tools/CameraShakeController.gd"),
|
||||||
|
ToolType.ANCHOR : preload("res://addons/reedcamera/scripts/camera_tools/CameraAnchorController.gd"),
|
||||||
|
ToolType.FOLLOWER : preload("res://addons/reedcamera/scripts/camera_tools/CameraFollowController.gd")
|
||||||
|
}
|
||||||
|
|
||||||
var _camera: Camera2D
|
var _camera: Camera2D
|
||||||
var _editor_valid := false
|
var _editor_valid := false
|
||||||
var _runtime_registered := false
|
var _runtime_registered := false
|
||||||
|
|
@ -17,6 +31,7 @@ var _pos_dirty := false
|
||||||
var _offset_dirty := false
|
var _offset_dirty := false
|
||||||
var _zoom_dirty := false
|
var _zoom_dirty := false
|
||||||
|
|
||||||
|
|
||||||
func _enter_tree() -> void:
|
func _enter_tree() -> void:
|
||||||
if Engine.is_editor_hint():
|
if Engine.is_editor_hint():
|
||||||
call_deferred("_editor_verify")
|
call_deferred("_editor_verify")
|
||||||
|
|
@ -123,9 +138,8 @@ func _ready() -> void:
|
||||||
if Engine.is_editor_hint():
|
if Engine.is_editor_hint():
|
||||||
return
|
return
|
||||||
|
|
||||||
_camera = _find_camera()
|
|
||||||
if not _camera:
|
if not _camera:
|
||||||
return
|
_camera = _find_camera()
|
||||||
|
|
||||||
_request_register()
|
_request_register()
|
||||||
|
|
||||||
|
|
@ -169,6 +183,8 @@ func _emit_config_warning() -> void:
|
||||||
## =========================
|
## =========================
|
||||||
##获取相机
|
##获取相机
|
||||||
func get_camera() -> Camera2D:
|
func get_camera() -> Camera2D:
|
||||||
|
if not _camera:
|
||||||
|
_camera = _find_camera()
|
||||||
return _camera
|
return _camera
|
||||||
|
|
||||||
##获取特定工具
|
##获取特定工具
|
||||||
|
|
@ -178,6 +194,10 @@ func get_tool(tool_class: Script) -> Node:
|
||||||
return c
|
return c
|
||||||
return null
|
return null
|
||||||
|
|
||||||
|
##通过类型返回工具
|
||||||
|
func get_tool_by_type(type:ToolType) -> Node:
|
||||||
|
return get_tool(type_script_map.get(type))
|
||||||
|
|
||||||
##获取所有工具
|
##获取所有工具
|
||||||
func get_tools() -> Array[CameraToolBasic]:
|
func get_tools() -> Array[CameraToolBasic]:
|
||||||
var out: Array[CameraToolBasic] = []
|
var out: Array[CameraToolBasic] = []
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
@tool
|
||||||
|
extends Node2D
|
||||||
|
class_name ScreenRatioRect
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# Internal State
|
||||||
|
# ===============================
|
||||||
|
var _rect: Rect2 = Rect2()
|
||||||
|
var _line_color: Color = Color(0.2, 0.9, 0.4, 0.9)
|
||||||
|
var _line_width: float = 2.0
|
||||||
|
|
||||||
|
var _target_node: Node2D = null
|
||||||
|
var _target_screen_pos: Vector2 = Vector2.ZERO
|
||||||
|
var _target_radius: float = 6.0
|
||||||
|
var _target_color: Color = Color(1, 0.3, 0.3, 0.9)
|
||||||
|
|
||||||
|
func _process(_delta: float) -> void:
|
||||||
|
if Engine.is_editor_hint():
|
||||||
|
return
|
||||||
|
|
||||||
|
if _target_node:
|
||||||
|
_update_target_screen_pos()
|
||||||
|
queue_redraw()
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# Public API
|
||||||
|
# ===============================
|
||||||
|
## 通过屏幕比例设置(0~1)
|
||||||
|
func set_ratio(ratio: Vector2) -> void:
|
||||||
|
var viewport_size := get_viewport_rect().size
|
||||||
|
var size := viewport_size * ratio
|
||||||
|
var pos := (viewport_size - size) * 0.5
|
||||||
|
set_rect(Rect2(pos, size))
|
||||||
|
|
||||||
|
## 直接设置屏幕空间 Rect
|
||||||
|
func set_rect(rect: Rect2) -> void:
|
||||||
|
_rect = rect
|
||||||
|
queue_redraw()
|
||||||
|
|
||||||
|
## 设置绘制风格
|
||||||
|
func set_style(color: Color, width: float = 2.0) -> void:
|
||||||
|
_line_color = color
|
||||||
|
_line_width = width
|
||||||
|
queue_redraw()
|
||||||
|
|
||||||
|
## 设置追踪点
|
||||||
|
func set_target_node(node: Node2D) -> void:
|
||||||
|
_target_node = node
|
||||||
|
_update_target_screen_pos()
|
||||||
|
queue_redraw()
|
||||||
|
|
||||||
|
## 更新targetnode在屏幕的位置
|
||||||
|
func _update_target_screen_pos() -> void:
|
||||||
|
if not _target_node:
|
||||||
|
return
|
||||||
|
|
||||||
|
_target_screen_pos = \
|
||||||
|
_target_node.get_global_transform_with_canvas().get_origin()
|
||||||
|
|
||||||
|
## 可选:快速隐藏 / 显示
|
||||||
|
func clear() -> void:
|
||||||
|
_target_node = null
|
||||||
|
_rect = Rect2()
|
||||||
|
queue_redraw()
|
||||||
|
|
||||||
|
# ===============================
|
||||||
|
# Draw
|
||||||
|
# ===============================
|
||||||
|
func _draw() -> void:
|
||||||
|
if _rect.size == Vector2.ZERO:
|
||||||
|
return
|
||||||
|
|
||||||
|
var left := _rect.position.x
|
||||||
|
var right := _rect.position.x + _rect.size.x
|
||||||
|
var top := _rect.position.y
|
||||||
|
var bottom := _rect.position.y + _rect.size.y
|
||||||
|
|
||||||
|
var vp_size := get_viewport_rect().size
|
||||||
|
|
||||||
|
# 上边线
|
||||||
|
draw_line(
|
||||||
|
Vector2(0, top),
|
||||||
|
Vector2(vp_size.x, top),
|
||||||
|
_line_color,
|
||||||
|
_line_width
|
||||||
|
)
|
||||||
|
|
||||||
|
# 下边线
|
||||||
|
draw_line(
|
||||||
|
Vector2(0, bottom),
|
||||||
|
Vector2(vp_size.x, bottom),
|
||||||
|
_line_color,
|
||||||
|
_line_width
|
||||||
|
)
|
||||||
|
|
||||||
|
# 左边线
|
||||||
|
draw_line(
|
||||||
|
Vector2(left, 0),
|
||||||
|
Vector2(left, vp_size.y),
|
||||||
|
_line_color,
|
||||||
|
_line_width
|
||||||
|
)
|
||||||
|
|
||||||
|
# 右边线
|
||||||
|
draw_line(
|
||||||
|
Vector2(right, 0),
|
||||||
|
Vector2(right, vp_size.y),
|
||||||
|
_line_color,
|
||||||
|
_line_width
|
||||||
|
)
|
||||||
|
|
||||||
|
##绘制角色位置锚点
|
||||||
|
if _target_node:
|
||||||
|
draw_circle(_target_screen_pos, _target_radius, _target_color)
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
uid://dckyyfvj25bxf
|
||||||
|
|
@ -2,25 +2,82 @@ extends CameraToolBasic
|
||||||
class_name ReedCameraFollowController
|
class_name ReedCameraFollowController
|
||||||
|
|
||||||
const _CONSTANTS := preload("res://addons/reedcamera/_data/CameraSystemConst.gd")
|
const _CONSTANTS := preload("res://addons/reedcamera/_data/CameraSystemConst.gd")
|
||||||
|
const _DEBUG_TOOL := preload("res://addons/reedcamera/scripts/camera_tools/DeadZoneDebug.tscn")
|
||||||
|
|
||||||
@export_group("Dead Zone")
|
@export_group("Dead Zone")
|
||||||
@export var dead_zone_ratio := Rect2(
|
@export var dead_zone_ratio : Vector2 = Vector2(.6,.6)
|
||||||
Vector2.ZERO, # 屏幕中心
|
|
||||||
Vector2(0.4, 0.4) # 宽高(屏幕比例)
|
|
||||||
)
|
|
||||||
|
|
||||||
@export_group("Follow")
|
@export_group("Follow")
|
||||||
@export var enabled_follow: bool = true
|
@export var enabled_follow: bool = true
|
||||||
|
@export var follow_speed: float = 600.0 # 世界单位 / 秒
|
||||||
@export var follow_lerp := 0.12 # 0~1,越大越“跟手”,越小越“蔚蓝感”的滞后
|
@export var follow_lerp := 0.12 # 0~1,越大越“跟手”,越小越“蔚蓝感”的滞后
|
||||||
|
|
||||||
|
##TODO:后续添加一下Runtime的修改逻辑
|
||||||
|
@export_group("Debug")
|
||||||
|
@export var show_preview: bool = true
|
||||||
|
var _show_preview: bool = false:
|
||||||
|
set(value):
|
||||||
|
_update_debug(value)
|
||||||
|
_show_preview = value
|
||||||
|
@export var preview_color: Color = Color.AQUAMARINE
|
||||||
|
@export var preview_line_width : float = 2.0
|
||||||
|
|
||||||
|
enum State{
|
||||||
|
IDLE,
|
||||||
|
CHASING,
|
||||||
|
STATIC
|
||||||
|
}
|
||||||
|
|
||||||
|
## 用于描述和切换follower工具的状态
|
||||||
|
var _current_state: State = State.IDLE
|
||||||
|
|
||||||
|
##Follower工具绑定的followNode
|
||||||
var _follow_node2d : Node2D = null
|
var _follow_node2d : Node2D = null
|
||||||
var _desired_pos := Vector2.ZERO
|
##最终的位置
|
||||||
|
var _final_position: Vector2
|
||||||
|
|
||||||
|
##缓存全局系统
|
||||||
|
var _sys: Object = null
|
||||||
|
##缓存DebugTool
|
||||||
|
var _screen_ratio_rect_draw_tool: Node = null
|
||||||
|
##缓存camera
|
||||||
var _camera: Camera2D = null
|
var _camera: Camera2D = null
|
||||||
|
|
||||||
func _update_follow(delta: float) -> void:
|
func _ready() -> void:
|
||||||
|
_show_preview = show_preview
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
#print(_current_state)
|
||||||
|
if _current_state == State.IDLE:
|
||||||
|
return
|
||||||
|
if _current_state == State.CHASING or State.STATIC:
|
||||||
|
update_follow(delta)
|
||||||
|
|
||||||
|
func _update_debug(debug:bool) -> void:
|
||||||
|
if debug:
|
||||||
|
if _screen_ratio_rect_draw_tool:
|
||||||
|
var t := _screen_ratio_rect_draw_tool.get_child(0)
|
||||||
|
t.set_ratio(dead_zone_ratio)
|
||||||
|
t.set_target_node(_follow_node2d)
|
||||||
|
t.set_style(preview_color,preview_line_width)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
var t := _DEBUG_TOOL.instantiate()
|
||||||
|
self.add_child(t)
|
||||||
|
_screen_ratio_rect_draw_tool = t
|
||||||
|
|
||||||
|
t.get_child(0).set_ratio(dead_zone_ratio)
|
||||||
|
t.get_child(0).set_target_node(_follow_node2d)
|
||||||
|
t.get_child(0).set_style(preview_color,preview_line_width)
|
||||||
|
else:
|
||||||
|
if not _screen_ratio_rect_draw_tool:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
_screen_ratio_rect_draw_tool.get_child(0).clear()
|
||||||
|
|
||||||
|
func update_follow(delta: float) -> void:
|
||||||
if not enabled_follow:
|
if not enabled_follow:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not _follow_node2d:
|
if not _follow_node2d:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -28,41 +85,64 @@ func _update_follow(delta: float) -> void:
|
||||||
if not cam:
|
if not cam:
|
||||||
return
|
return
|
||||||
|
|
||||||
# 初始化
|
# 0. 读取相机的全局坐标
|
||||||
if not _initialized:
|
_final_position = cam.global_position
|
||||||
_pos = cam.global_position
|
|
||||||
_desired_pos = _pos
|
|
||||||
_initialized = true
|
|
||||||
|
|
||||||
var view_rect := _get_camera_view_rect(cam)
|
# 1. target 的屏幕坐标(Canvas Space)
|
||||||
var dead_rect := _get_dead_zone_world_rect(view_rect)
|
var t_in_screen :Vector2 = \
|
||||||
|
_follow_node2d.get_global_transform_with_canvas().get_origin()
|
||||||
|
|
||||||
var p := player.global_position
|
var screen_size : Vector2 = _get_camera_system().get_screen_size()
|
||||||
var delta_move := Vector2.ZERO
|
var screen_center : Vector2 = screen_size * 0.5
|
||||||
|
var dead_half : Vector2 = screen_size * dead_zone_ratio * 0.5
|
||||||
|
|
||||||
if p.x < dead_rect.position.x:
|
# 2. 获得移动方向
|
||||||
delta_move.x = p.x - dead_rect.position.x
|
var offset := \
|
||||||
elif p.x > dead_rect.position.x + dead_rect.size.x:
|
_compute_deadzone_offset(
|
||||||
delta_move.x = p.x - (dead_rect.position.x + dead_rect.size.x)
|
t_in_screen,
|
||||||
|
screen_center,
|
||||||
if p.y < dead_rect.position.y:
|
dead_half
|
||||||
delta_move.y = p.y - dead_rect.position.y
|
|
||||||
elif p.y > dead_rect.position.y + dead_rect.size.y:
|
|
||||||
delta_move.y = p.y - (dead_rect.position.y + dead_rect.size.y)
|
|
||||||
|
|
||||||
if delta_move != Vector2.ZERO:
|
|
||||||
_desired_pos += delta_move
|
|
||||||
|
|
||||||
# 可选 room clamp
|
|
||||||
if use_room_clamp:
|
|
||||||
_desired_pos = _desired_pos.clamp(
|
|
||||||
room_world_rect.position,
|
|
||||||
room_world_rect.position + room_world_rect.size
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 蔚蓝感:滞后 lerp
|
if offset == Vector2.ZERO:
|
||||||
_pos = _pos.lerp(_desired_pos, follow_lerp)
|
_current_state = State.STATIC
|
||||||
|
return
|
||||||
|
_current_state = State.CHASING
|
||||||
|
|
||||||
|
|
||||||
|
var move_dir := offset.normalized()
|
||||||
|
var world_velocity := (move_dir * follow_speed) / cam.zoom
|
||||||
|
##如果存在move_dir,则我们认为相机需要chasing player
|
||||||
|
|
||||||
|
var desired_pos := _final_position + world_velocity * delta
|
||||||
|
|
||||||
|
if follow_lerp > 0.0:
|
||||||
|
_final_position = cam.global_position.lerp(desired_pos, follow_lerp)
|
||||||
|
else:
|
||||||
|
_final_position = desired_pos
|
||||||
|
|
||||||
|
func _compute_deadzone_offset(
|
||||||
|
screen_pos: Vector2,
|
||||||
|
screen_center: Vector2,
|
||||||
|
dead_half: Vector2
|
||||||
|
) -> Vector2:
|
||||||
|
var o := Vector2.ZERO
|
||||||
|
var dx := screen_pos.x - screen_center.x
|
||||||
|
var dy := screen_pos.y - screen_center.y
|
||||||
|
|
||||||
|
if dx < -dead_half.x:
|
||||||
|
o.x = dx + dead_half.x
|
||||||
|
elif dx > dead_half.x:
|
||||||
|
o.x = dx - dead_half.x
|
||||||
|
|
||||||
|
if dy < -dead_half.y:
|
||||||
|
o.y = dy + dead_half.y
|
||||||
|
elif dy > dead_half.y:
|
||||||
|
o.y = dy - dead_half.y
|
||||||
|
|
||||||
|
return o
|
||||||
|
|
||||||
|
## 从相机指针获取相机组件
|
||||||
func _get_camera_from_pointer() -> Camera2D:
|
func _get_camera_from_pointer() -> Camera2D:
|
||||||
if _camera:
|
if _camera:
|
||||||
return _camera
|
return _camera
|
||||||
|
|
@ -74,11 +154,38 @@ func _get_camera_from_pointer() -> Camera2D:
|
||||||
|
|
||||||
return _camera
|
return _camera
|
||||||
|
|
||||||
func _get_camera_view_rect(cam: Camera2D) -> Rect2:
|
## 获取全局相机管理器
|
||||||
var screen_size := cam.get_viewport_rect().size
|
func _get_camera_system() -> Object:
|
||||||
var zoom := cam.zoom
|
if _sys:
|
||||||
zoom.x = maxf(zoom.x, 0.001)
|
return _sys
|
||||||
zoom.y = maxf(zoom.y, 0.001)
|
|
||||||
|
|
||||||
var size := screen_size / zoom
|
if Engine.has_singleton(_CONSTANTS.CAMERA_SYSTEM_NAME):
|
||||||
return Rect2(cam.global_position - size * 0.5, size)
|
_sys = Engine.get_singleton(_CONSTANTS.CAMERA_SYSTEM_NAME)
|
||||||
|
|
||||||
|
return _sys
|
||||||
|
|
||||||
|
|
||||||
|
##外部调用,设置一个相机系统的跟随者
|
||||||
|
func register_follower(follower: Node2D) -> void:
|
||||||
|
_follow_node2d = follower
|
||||||
|
if self._current_state == State.IDLE:
|
||||||
|
start_follow()
|
||||||
|
|
||||||
|
##外部调用,移除一共相机系统的跟随者
|
||||||
|
func unregister_follower() -> void:
|
||||||
|
_follow_node2d = null
|
||||||
|
stop_follow()
|
||||||
|
|
||||||
|
##外部调用,开始跟随
|
||||||
|
func start_follow() -> void:
|
||||||
|
_current_state = State.STATIC
|
||||||
|
|
||||||
|
##外部调用,结束跟随
|
||||||
|
func stop_follow() -> void:
|
||||||
|
_current_state = State.IDLE
|
||||||
|
|
||||||
|
func get_base_position() -> Vector2:
|
||||||
|
return _final_position
|
||||||
|
|
||||||
|
func has_base_position() -> bool:
|
||||||
|
return _current_state == State.CHASING
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ var _current_offset := Vector2.ZERO
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
if Engine.is_editor_hint():
|
if Engine.is_editor_hint():
|
||||||
return
|
return
|
||||||
|
|
||||||
set_process(true)
|
set_process(true)
|
||||||
|
|
||||||
func _exit_tree() -> void:
|
func _exit_tree() -> void:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://csx2bji7s6xnl"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://dckyyfvj25bxf" path="res://addons/reedcamera/scripts/ScreenRatioRect.gd" id="1_ljod6"]
|
||||||
|
|
||||||
|
[node name="DeadZoneDebug" type="CanvasLayer"]
|
||||||
|
layer = 1000
|
||||||
|
|
||||||
|
[node name="ScreenRatioRect" type="Node2D" parent="."]
|
||||||
|
script = ExtResource("1_ljod6")
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
class_name STT_Autoload extends SceneTriggerTarget
|
||||||
|
|
||||||
|
@export var autoload_name: StringName
|
||||||
|
|
||||||
|
func get_effect_target(owner: Node) -> Object:
|
||||||
|
return owner.get_tree().root.get_node_or_null("/root/%s" % autoload_name)
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
uid://cwxwsfl1mx7kc
|
||||||
Loading…
Reference in New Issue