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.
183 lines
6.2 KiB
GDScript
183 lines
6.2 KiB
GDScript
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, 2.95) # 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, 2)
|
|
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 /2:
|
|
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 - 0.4
|
|
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_new: Vector2): level_size = size_new
|
|
|
|
func on_level_pos_change(pos_new: Vector2): level_pos = pos_new
|
|
|
|
|
|
func on_level_loading_end():
|
|
refresh_target_pos()
|
|
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
|