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.
		
		
		
		
		
			
		
			
				
	
	
		
			175 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			GDScript
		
	
			
		
		
	
	
			175 lines
		
	
	
		
			6.7 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
 | |
| var offset: float                      = 10
 | |
| var shake_offset_x: float
 | |
| var camera_limit: Vector3              = Vector3(6.4, 1.04, 3.6) #x,up,z-downd
 | |
| 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.0
 | |
| 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] = []
 | |
| @onready var grid_block_material: Material = load("res://render/material/grid_block.tres") as Material
 | |
| 
 | |
| 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_hit_floor.connect(on_character_hit_floor)
 | |
|     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)
 | |
| 
 | |
| 
 | |
| 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 - 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)
 | |
|             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):
 | |
|     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
 | |
| 
 | |
| 
 | |
| 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] = Util.snap_float(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_character_hit_floor(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
 | |
|         refresh_target_pos()
 | |
| 
 | |
| 
 | |
| func on_character_hit_floor(id: int, pos: Vector3):
 | |
|     if id == target:
 | |
|         target_pos_y = pos.y
 | |
|         refresh_target_pos()
 | |
|         grid_block_material.set_shader_parameter("target_position", pos)
 | |
| 
 | |
| 
 | |
| func refresh_target_pos():
 | |
|     var pos: Vector2            = target_character_pos
 | |
|     var camera_size_diff: float = (camera_size - size)/2.0
 | |
|     var x_min: float            = camera_limit.x - camera_size_diff
 | |
|     var x_max: float            = level_size.x - camera_limit.x + camera_size_diff
 | |
|     var y_min: float            = camera_limit.y - target_pos_y - camera_size_diff
 | |
|     var y_max: float            = 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: 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:
 | |
|     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.4 * 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
 | |
|     
 |