|  |  |  | extends Camera3D | 
					
						
							|  |  |  | class_name CameraManager | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @export var global_effect_curve: Curve | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var target: int | 
					
						
							|  |  |  | var target_character_pos: Vector2      = Vector2.ZERO | 
					
						
							|  |  |  | var target_pos: Vector2                = Vector2.ZERO | 
					
						
							|  |  |  | var target_pos_y: float | 
					
						
							|  |  |  | var target_pos_now: Vector2            = Vector2.ZERO | 
					
						
							|  |  |  | var level_size: Vector2                = Vector2(12.8, 7.68) | 
					
						
							|  |  |  | var level_pos: Vector2                 = Vector2.ZERO | 
					
						
							|  |  |  | var offset: float                      = 10 | 
					
						
							|  |  |  | var shake_offset_x: float | 
					
						
							|  |  |  | var camera_limit: Vector3              = Vector3(6.4, 1.7, 3.58) #x,z-up,z-down | 
					
						
							|  |  |  | var camera_size: float                 = 7.2 | 
					
						
							|  |  |  | var basic_size: Vector2                = Vector2(640, 360) | 
					
						
							|  |  |  | var scale_y: float                     = cos(deg_to_rad(45.0)) * 2.0 #1.414 | 
					
						
							|  |  |  | var sample_rate: float                 = 3.6 | 
					
						
							|  |  |  | var stage_size: Vector2                = basic_size * sample_rate | 
					
						
							|  |  |  | var stage_scale: Vector2               = Vector2(1, scale_y) / sample_rate | 
					
						
							|  |  |  | var stage_offset_y: float              = (scale_y - 1.0) * 0.5 / sample_rate * stage_size.y | 
					
						
							|  |  |  | var screen_pos_scale: Vector2          = Vector2(sample_rate, sample_rate/scale_y) | 
					
						
							|  |  |  | var screen_pos_offset: Vector2         = Vector2(0, -stage_offset_y) | 
					
						
							|  |  |  | var global_effect_list: Array[Variant] = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class GlobalEffect: | 
					
						
							|  |  |  |     var effect_type: Enum.EGlobalEffect | 
					
						
							|  |  |  |     var life_time: float | 
					
						
							|  |  |  |     var life_time_now: float | 
					
						
							|  |  |  |     var value: float | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func _ready(): | 
					
						
							|  |  |  |     Global.camera_mgr = self | 
					
						
							|  |  |  |     SignalManager.character_create.connect(on_character_create) | 
					
						
							|  |  |  |     SignalManager.character_pos_changed.connect(on_character_pos_changed) | 
					
						
							|  |  |  |     SignalManager.character_destroy.connect(on_character_destroy) | 
					
						
							|  |  |  |     SignalManager.level_size_change.connect(on_level_size_change) | 
					
						
							|  |  |  |     SignalManager.level_pos_change.connect(on_level_pos_change) | 
					
						
							|  |  |  |     SignalManager.level_loading_end.connect(on_level_loading_end) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func _process(delta): | 
					
						
							|  |  |  |     update_global_effect(delta) | 
					
						
							|  |  |  |     update_camera_pos(delta) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func update_global_effect(delta): | 
					
						
							|  |  |  |     var remove_list: Array[Variant] = [] | 
					
						
							|  |  |  |     for global_effect: GlobalEffect in global_effect_list: | 
					
						
							|  |  |  |         global_effect.life_time_now += delta | 
					
						
							|  |  |  |         global_effect.life_time_now = min(global_effect.life_time_now, global_effect.life_time) | 
					
						
							|  |  |  |         if global_effect.life_time_now == global_effect.life_time: | 
					
						
							|  |  |  |             remove_list.append(global_effect) | 
					
						
							|  |  |  |         var rate: float  = global_effect.life_time_now/global_effect.life_time | 
					
						
							|  |  |  |         var value: float = global_effect_curve.sample(rate)*global_effect.value | 
					
						
							|  |  |  |         match global_effect.effect_type: | 
					
						
							|  |  |  |             Enum.EGlobalEffect.CameraSize: | 
					
						
							|  |  |  |                 size = camera_size * (1 - value) | 
					
						
							|  |  |  |                 refresh_target_pos() | 
					
						
							|  |  |  |             Enum.EGlobalEffect.CameraShake: | 
					
						
							|  |  |  |                 shake_offset_x = (sin(rate * PI * 10) - 0.5)*0.04*value | 
					
						
							|  |  |  |             Enum.EGlobalEffect.ColorShift: | 
					
						
							|  |  |  |                 Global.view_mgr.set_post_processing("shift_strength", value) | 
					
						
							|  |  |  |             Enum.EGlobalEffect.Blur: | 
					
						
							|  |  |  |                 Global.view_mgr.set_post_processing("blur_strength", value) | 
					
						
							|  |  |  |             Enum.EGlobalEffect.SpeedLine: | 
					
						
							|  |  |  |                 Global.view_mgr.set_post_processing("speed_line_strength", value) | 
					
						
							|  |  |  |             _: pass | 
					
						
							|  |  |  |     for global_effect: GlobalEffect in remove_list: | 
					
						
							|  |  |  |         global_effect_list.erase(global_effect) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func update_camera_pos(delta): | 
					
						
							|  |  |  |     target_pos_lerp(0, delta, 6) | 
					
						
							|  |  |  |     target_pos_lerp(1, delta, 6) | 
					
						
							|  |  |  |     position.x = (target_pos_now.x + shake_offset_x) | 
					
						
							|  |  |  |     position.z = (target_pos_now.y + target_pos_y + offset) | 
					
						
							|  |  |  |     position.y = (target_pos_y + offset) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func target_pos_lerp(index: int, delta: float, delta_scale: float): | 
					
						
							|  |  |  |     var target_pos_real: Vector2 = target_pos | 
					
						
							|  |  |  |     var diff                     = abs(target_pos_now[index] - target_pos_real[index]) | 
					
						
							|  |  |  |     if diff < Setting.pixel_size: | 
					
						
							|  |  |  |         target_pos_now[index] = target_pos_real[index] | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         var weight_min = Setting.pixel_size / 2 / diff | 
					
						
							|  |  |  |         var weight     = max(delta * delta_scale, weight_min) | 
					
						
							|  |  |  |         target_pos_now[index] = lerp(target_pos_now[index], target_pos_real[index], weight) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func on_character_create(id: int, type: int, pos: Vector3): | 
					
						
							|  |  |  |     if type == Enum.ECharacterType.Player: | 
					
						
							|  |  |  |         target = id | 
					
						
							|  |  |  |         on_character_pos_changed(id, pos) | 
					
						
							|  |  |  |         on_level_loading_end() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func on_character_pos_changed(id: int, pos: Vector3): | 
					
						
							|  |  |  |     if id == target: | 
					
						
							|  |  |  |         target_character_pos.x = pos.x | 
					
						
							|  |  |  |         target_character_pos.y = pos.z | 
					
						
							|  |  |  |         target_pos_y = pos.y | 
					
						
							|  |  |  |         refresh_target_pos() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func on_character_destroy(id: int): target = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func refresh_target_pos(): | 
					
						
							|  |  |  |     var pos: Vector2            = target_character_pos | 
					
						
							|  |  |  |     var camera_size_diff: float = (camera_size - size)/2.0 | 
					
						
							|  |  |  |     var x_min: float            = level_pos.x + camera_limit.x - camera_size_diff | 
					
						
							|  |  |  |     var x_max: float            = level_pos.x + level_size.x - camera_limit.x + camera_size_diff | 
					
						
							|  |  |  |     var y_min: float            = level_pos.y + camera_limit.y - target_pos_y - camera_size_diff | 
					
						
							|  |  |  |     var y_max: float            = level_pos.y + level_size.y - camera_limit.z - target_pos_y + camera_size_diff | 
					
						
							|  |  |  |     target_pos.x = Util.snap_float(clamp(pos.x, x_min, x_max)) | 
					
						
							|  |  |  |     target_pos.y = Util.snap_float(clamp(pos.y-target_pos_y, y_min, y_max)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func on_level_size_change(size: Vector2): level_size = size | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func on_level_pos_change(pos: Vector2): level_pos = pos | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func on_level_loading_end(): | 
					
						
							|  |  |  |     target_pos_now.x = target_pos.x | 
					
						
							|  |  |  |     target_pos_now.y = target_pos.y | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func get_screen_pos(pos: Vector3) -> Vector2: | 
					
						
							|  |  |  |     var ret: Vector2 = unproject_position(pos) | 
					
						
							|  |  |  |     ret.x /= screen_pos_scale.x | 
					
						
							|  |  |  |     ret.y /= screen_pos_scale.y | 
					
						
							|  |  |  |     ret.x += screen_pos_offset.x | 
					
						
							|  |  |  |     ret.y += screen_pos_offset.y | 
					
						
							|  |  |  |     return ret | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func add_global_effect(effect_type: Enum.EGlobalEffect, life_time: float, value: float) -> void: | 
					
						
							|  |  |  |     value *= 0.5 | 
					
						
							|  |  |  |     for global_effect: GlobalEffect in global_effect_list: | 
					
						
							|  |  |  |         if global_effect.effect_type == effect_type: | 
					
						
							|  |  |  |             global_effect.life_time = life_time | 
					
						
							|  |  |  |             global_effect.life_time_now = 0 | 
					
						
							|  |  |  |             global_effect.value = value | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |     var global_effect = GlobalEffect.new() | 
					
						
							|  |  |  |     global_effect.effect_type = effect_type | 
					
						
							|  |  |  |     global_effect.life_time = life_time | 
					
						
							|  |  |  |     global_effect.life_time_now = 0 | 
					
						
							|  |  |  |     global_effect.value = value | 
					
						
							|  |  |  |     global_effect_list.append(global_effect) | 
					
						
							|  |  |  |     return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func effect(pause_time) -> void: | 
					
						
							|  |  |  |     if not pause_time: | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     var basic_pause_time: float = 0.3 | 
					
						
							|  |  |  |     var effect_time             = pause_time * 2 | 
					
						
							|  |  |  |     var rate                    = pause_time/basic_pause_time | 
					
						
							|  |  |  |     add_global_effect(Enum.EGlobalEffect.CameraShake, effect_time, 0.8 * rate) | 
					
						
							|  |  |  |     add_global_effect(Enum.EGlobalEffect.CameraSize, effect_time, 0.1 * rate) | 
					
						
							|  |  |  |     add_global_effect(Enum.EGlobalEffect.ColorShift, effect_time, 0.8 * rate) | 
					
						
							|  |  |  |     add_global_effect(Enum.EGlobalEffect.Blur, effect_time, 0.8 * rate) | 
					
						
							|  |  |  |     #add_global_effect(Enum.EGlobalEffect.SpeedLine,effect_time,0.2* rate) | 
					
						
							|  |  |  |     return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func effect_shake(pause_time) -> void: | 
					
						
							|  |  |  |     if not pause_time: | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     var basic_pause_time: float = 0.3 | 
					
						
							|  |  |  |     var effect_time             = pause_time * 2 | 
					
						
							|  |  |  |     var rate                    = pause_time/basic_pause_time | 
					
						
							|  |  |  |     add_global_effect(Enum.EGlobalEffect.CameraShake, effect_time, 0.8 * rate) | 
					
						
							|  |  |  |     return |