extends Camera2D var horizontal_facing = 0 var vertical_facing = 0 var camera_vertical_shift = 0 var right_move_time: float = 0 var left_move_time: float = 0 var slow_time: float = 0 var original_limit_left: int var original_limit_right: int var original_limit_bottom: int var original_limit_top: int var camera_is_panning: bool = false var target_offset: Vector2 = Vector2(0,0) export var camera_horizontal_shift = 60 export var offset_reset_seconds := 1 export var offset_adapt_seconds := 1 onready var levelState := $"%LevelState" onready var signalManager := $"%SignalManager" onready var shiftLeft = $CameraAnimationPlayer.get_animation("shiftingLeft") onready var shiftRight = $CameraAnimationPlayer.get_animation("shiftingRight") onready var shiftCenter = $CameraAnimationPlayer.get_animation("shiftingCenter") onready var anim_player = $CameraAnimationPlayer onready var original_x_zoom = zoom.x onready var original_y_zoom = zoom.y onready var blobby = get_node("%Blobby") onready var screen_rect = Vector2(ProjectSettings.get_setting("display/window/size/width") * zoom.x, ProjectSettings.get_setting("display/window/size/height") * zoom.y ) var image = Image.new() var texture = ImageTexture.new() var prev_pos: Vector2 # Gets the camera limits from the tilemap of the level # Requires "TileMap" to be a sibling of blobby func _ready(): _set_boundaries() print(screen_rect) self.position = blobby.global_position image.create(128, 2, false, Image.FORMAT_RGBAH) # TODO Test Performance _update_lighting_shader() # TODO Trigger when needed signalManager.connect("terminal_activated", self, "_on_SignalManager_terminal_activated") signalManager.connect("player_died", self, "_death_cam") func _on_SignalManager_terminal_activated(): get_node("LightAnimationPlayer").play("Pulsing") func _physics_process(delta: float) -> void: if(anim_player.is_playing()): position = blobby.position prev_pos = position _update_lighting_shader() return var player_vel = (blobby.position - prev_pos)/delta # TODO Take average of velocity here if(abs(player_vel.x) >= blobby.max_velocity["walk"] * 0.97 && (sign(player_vel.x) == sign(target_offset.x) || target_offset.x == 0)): if(player_vel.x > 0): right_move_time += delta left_move_time = max(0, left_move_time - delta) slow_time = max(0, slow_time - delta) else: left_move_time += delta right_move_time = max(0, right_move_time - delta) slow_time = max(0, slow_time - delta) elif(abs(player_vel.x) <= blobby.max_velocity["walk"] * 0.9 || sign(player_vel.x) != sign(target_offset.x) || target_offset.x == 0): slow_time += delta left_move_time = max(0, left_move_time - delta) right_move_time = max(0, right_move_time - delta) _adapt_to_movement(player_vel) position = blobby.position prev_pos = position _update_lighting_shader() func _set_boundaries(): # This is ok, because it only happens on initialization # But it is also quite fickle var tilemap = get_node("./%TileMap") # TODO: This goes wrong when overwriting old tiles with new sprites # New pngs -> completely new tiles and rebuild map var rect = tilemap.get_used_rect() var cell_size = tilemap.cell_size limit_right = rect.end.x * cell_size.x limit_left = rect.position.x * cell_size.x limit_top = rect.position.y * cell_size.y limit_bottom = rect.end.y * cell_size.y original_limit_left = limit_left original_limit_right = limit_right original_limit_top = limit_top original_limit_bottom = limit_bottom var screen_size = get_viewport_rect() var h_pixels = limit_right - limit_left var v_pixels = limit_bottom - limit_top # TODO: Fix that it can zoom both? if screen_size.end.x * original_x_zoom - h_pixels > 0: zoom.x = h_pixels / screen_size.end.x zoom.y = zoom.x if screen_size.end.y * original_y_zoom - v_pixels > 0: zoom.y = v_pixels / screen_size.end.y zoom.x = zoom.y # Smoothing the camera limits in godot ruins something func _adapt_to_movement(velocity: Vector2) -> void: var offset_track var center = get_camera_screen_center() var left_edge_pos = center.x - screen_rect.x/2 + camera_horizontal_shift var right_edge_pos = center.x + screen_rect.x/2 - camera_horizontal_shift if(left_move_time >= offset_adapt_seconds && !anim_player.is_playing()): left_move_time = 0 target_offset.x = -camera_horizontal_shift if(offset == target_offset || left_edge_pos + target_offset.x - 24 < limit_left || right_edge_pos + target_offset.x + 24 > limit_right ): return offset_track = shiftLeft.find_track(".:offset") shiftLeft.track_set_key_value(offset_track, 0, offset) shiftLeft.track_set_key_value(offset_track, 1, target_offset) # limit_left = original_limit_left + camera_horizontal_shift var limit_left_track = shiftLeft.find_track(".:limit_left") var new_limit_left = original_limit_left + camera_horizontal_shift shiftLeft.track_set_key_value(limit_left_track, 0, limit_left) shiftLeft.track_set_key_value(limit_left_track, 1, new_limit_left) anim_player.play("shiftingLeft") elif(right_move_time >= offset_adapt_seconds && !anim_player.is_playing()): right_move_time = 0 target_offset.x = camera_horizontal_shift if(offset == target_offset || left_edge_pos + target_offset.x - 24 < limit_left || right_edge_pos + target_offset.x + 24 > limit_right ): return offset_track = shiftRight.find_track(".:offset") shiftRight.track_set_key_value(offset_track, 0, offset) shiftRight.track_set_key_value(offset_track, 1, target_offset) # limit_right = original_limit_right - camera_horizontal_shift var limit_right_track = shiftRight.find_track(".:limit_right") var new_limit_right = original_limit_right - camera_horizontal_shift shiftRight.track_set_key_value(limit_right_track, 0, limit_right) shiftRight.track_set_key_value(limit_right_track, 1, new_limit_right) anim_player.play("shiftingRight") elif(slow_time >= offset_reset_seconds): slow_time = 0 target_offset.x = 0 if(offset == target_offset): return if(left_edge_pos > limit_left && limit_right > right_edge_pos): offset_track = shiftCenter.find_track(".:offset") shiftCenter.track_set_key_value(offset_track, 0, offset) shiftCenter.track_set_key_value(offset_track, 1, target_offset) var limit_left_track = shiftCenter.find_track(".:limit_left") var limit_right_track = shiftCenter.find_track(".:limit_right") var limit_top_track = shiftCenter.find_track(".:limit_top") var limit_bottom_track = shiftCenter.find_track(".:limit_bottom") shiftCenter.track_set_key_value(limit_left_track, 0, limit_left) shiftCenter.track_set_key_value(limit_right_track, 0, limit_right) shiftCenter.track_set_key_value(limit_top_track, 0, limit_top) shiftCenter.track_set_key_value(limit_bottom_track, 0, limit_bottom) shiftCenter.track_set_key_value(limit_left_track, 1, original_limit_left) shiftCenter.track_set_key_value(limit_right_track, 1,original_limit_right) shiftCenter.track_set_key_value(limit_top_track, 1, original_limit_top) shiftCenter.track_set_key_value(limit_bottom_track, 1, original_limit_bottom) anim_player.play("shiftingCenter") return func reset_limits() -> void: limit_left = original_limit_left limit_right = original_limit_right limit_bottom = original_limit_bottom limit_top = original_limit_top func _death_cam(): $CameraAnimationPlayer.play("deathCamJustZoom") func _update_lighting_shader(): # Props to gameendaevour # TODO get this into a central world update management system var lights = get_tree().get_nodes_in_group("light") image.lock() for i in lights.size(): var light = lights[i] # TODO To make the lighting affect all layers properly # I would have the access the global positions of nodes in different Z layers # without the projection to the global center layer. # var vtrans = get_canvas_transform() # var top_left = -vtrans.origin / vtrans.get_scale() # var vsize = get_viewport_rect().size # var t = Transform2D(0, (top_left + 0.5*vsize/vtrans.get_scale()).rotated(rotation)) image.set_pixel(i, 0, Color( light.position.x, light.position.y, light.strength, light.radius )) image.set_pixel(i, 1, light.color) image.unlock() texture.create_from_image(image) material.set_shader_param("n_lights", lights.size()) material.set_shader_param("light_data", texture) material.set_shader_param("global_transform", get_global_transform()) material.set_shader_param("viewport_transform", get_viewport_transform())