You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

150 lines
5.4 KiB
GDScript

2 years ago
extends Camera3D
class_name CameraManager
@export var global_effect_curve : Curve
2 years ago
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
var offset:float = 5
var shake_offset_x:float
var camera_limit = Vector3(6.4,1.04,3.6) #x,up,z-downd
var camera_size = 7.2
2 years ago
var basic_size = Vector2(640,360)
var scale_y = cos(deg_to_rad(45.0)) * 2.0 #1.414
var sample_rate = 3.0
var stage_size = basic_size * sample_rate
var stage_scale = Vector2(1,scale_y) / sample_rate
var stage_offset_y = (scale_y - 1.0) * 0.5 / sample_rate * stage_size.y
var screen_pos_scale = Vector2(sample_rate,sample_rate/scale_y)
var screen_pos_offset = Vector2(0,-stage_offset_y)
2 years ago
var global_effect_list = []
class GlobalEffect:
var effect_type : Enum.EGlobalEffect
var life_time : float
var life_time_now : float
var value : float
2 years ago
func _ready():
Global.camera_mgr = self
2 years ago
SignalManager.character_create.connect(on_character_create)
SignalManager.character_pos_changed.connect(on_character_pos_changed)
2 years ago
SignalManager.character_hit_floor.connect(on_character_hit_floor)
2 years ago
SignalManager.character_destroy.connect(on_character_destroy)
SignalManager.level_size_change.connect(on_level_size_change)
SignalManager.level_loading_end.connect(on_level_loading_end)
2 years ago
func _process(delta):
update_global_effect(delta)
update_camera_pos(delta)
func update_global_effect(delta):
var remove_list = []
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 = global_effect.life_time_now/global_effect.life_time
var value = global_effect_curve.sample(rate)*global_effect.value
match global_effect.effect_type:
Enum.EGlobalEffect.CameraSize:size = camera_size * (1 - 0.2*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)
2 years ago
Enum.EGlobalEffect.SpeedLine:Global.view_mgr.set_post_processing("speed_line_strength",value)
for global_effect : GlobalEffect in remove_list:
global_effect_list.erase(global_effect)
func update_camera_pos(delta):
2 years ago
target_pos_lerp(0,delta,5)
target_pos_lerp(1,delta,5)
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
2 years ago
func target_pos_lerp(index:int,delta:float,delta_scale:float):
var target_pos_real = target_pos
var diff = abs(target_pos_now[index] - target_pos_real[index])
if diff < Setting.pixel_size:
target_pos_now[index] = Util.snap_float(target_pos_real[index])
2 years ago
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)
2 years ago
2 years ago
func on_character_create(id:int,type:int,pos:Vector3):
if type == Enum.ECharacterType.Player:
2 years ago
target = id
on_character_pos_changed(id,pos)
on_character_hit_floor(id,pos)
on_level_loading_end()
2 years ago
func on_character_pos_changed(id:int,pos:Vector3):
if id == target:
target_character_pos.x = pos.x
target_character_pos.y = pos.z
refresh_target_pos()
2 years ago
2 years ago
func on_character_hit_floor(id:int,pos:Vector3):
if id == target:
target_pos_y = pos.y
refresh_target_pos()
func refresh_target_pos():
var pos = target_character_pos
var camera_size_diff = (camera_size - size)/2.0
var x_min = camera_limit.x - camera_size_diff
var x_max = level_size.x - camera_limit.x + camera_size_diff
var y_min = camera_limit.y - target_pos_y - camera_size_diff
var y_max = level_size.y - camera_limit.z - target_pos_y + camera_size_diff
target_pos.x = clamp(pos.x,x_min,x_max)
target_pos.y = clamp(pos.y-target_pos_y,y_min,y_max)
func on_character_destroy(id:int):target = 0
func on_level_size_change(size:Vector2):level_size = size
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 = unproject_position(pos)
ret.x /= screen_pos_scale.x
ret.y /= screen_pos_scale.y
2 years ago
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):
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)
func effect(pause_time):
if not pause_time:
return
var basic_pause_time = 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.4 * rate)
add_global_effect(Enum.EGlobalEffect.ColorShift,effect_time,0.8 * rate)
add_global_effect(Enum.EGlobalEffect.Blur,effect_time,0.8 * rate)
2 years ago
#add_global_effect(Enum.EGlobalEffect.SpeedLine,effect_time,0.2* rate)