Invincibility Shader (simple) New Death Shader dissolving Pit Areas Invincibility fixes for spikes and flying laser cutters Vending Machine Better global and level stats tracking
207 lines
8.3 KiB
GDScript
207 lines
8.3 KiB
GDScript
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())
|