CameraHandler.gd 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. class_name CameraHandler
  2. extends Node2D
  3. @onready var last_position = global_position
  4. @export var camera: Camera2D = null
  5. @export var camera_center_joint: Node2D = null
  6. var camera_position := Vector2.ZERO
  7. var camera_offset := Vector2(8, 0)
  8. var camera_right_limit := 9999999
  9. var player_offset := 0.0
  10. var can_scroll_left := true
  11. var can_scroll_right := true
  12. static var cam_locked := false
  13. var scrolling := false
  14. var cam_direction := 1
  15. func _exit_tree() -> void:
  16. cam_locked = false
  17. func _physics_process(delta: float) -> void:
  18. handle_camera(delta)
  19. last_position = global_position
  20. func handle_camera(delta: float) -> void:
  21. can_scroll_left = camera_position.x + camera_offset.x > -255
  22. can_scroll_right = camera_position.x + camera_offset.x < camera_right_limit - 1
  23. if ["Pipe", "Climb", "FlagPole"].has(owner.state_machine.state.name):
  24. handle_vertical_scrolling(delta)
  25. do_limits()
  26. camera.global_position = camera_position + camera_offset
  27. return
  28. if not cam_locked:
  29. handle_horizontal_scrolling(delta)
  30. handle_vertical_scrolling(delta)
  31. handle_offsets(delta)
  32. do_limits()
  33. camera.global_position = camera_position + camera_offset
  34. update_camera_barriers()
  35. func update_camera_barriers() -> void:
  36. if get_viewport() != null:
  37. camera_center_joint.global_position = get_viewport().get_camera_2d().get_screen_center_position()
  38. camera_center_joint.get_node("LeftWall").position.x = -(get_viewport_rect().size.x / 2)
  39. camera_center_joint.get_node("RightWall").position.x = (get_viewport_rect().size.x / 2)
  40. func handle_horizontal_scrolling(delta: float) -> void:
  41. scrolling = false
  42. var true_velocity = (global_position - last_position) / delta
  43. var true_vel_dir = sign(true_velocity.x)
  44. if (owner.is_on_wall() and owner.direction == -owner.get_wall_normal().x):
  45. true_vel_dir = 0
  46. true_velocity.x = 0
  47. ## RIGHT MOVEMENT
  48. if true_vel_dir == 1 and can_scroll_right:
  49. cam_direction = 1
  50. if global_position.x >= camera_position.x:
  51. var offset = 0
  52. scrolling = true
  53. if camera_position.x <= global_position.x - 4:
  54. offset = camera_position.x - global_position.x + abs(true_velocity.x * delta)
  55. camera_position.x = global_position.x + offset
  56. elif global_position.x >= camera_position.x - get_viewport_rect().size.x / 8:
  57. if true_velocity.x > 75:
  58. camera_position.x += true_velocity.x * delta / 2
  59. else:
  60. camera_position.x += true_velocity.x * delta
  61. ## LEFT MOVEMENT
  62. elif true_vel_dir == -1 and can_scroll_left and Global.current_level.can_backscroll:
  63. cam_direction = -1
  64. if global_position.x <= camera_position.x:
  65. scrolling = true
  66. var offset = 0
  67. if camera_position.x >= global_position.x + 4:
  68. offset = camera_position.x - global_position.x - abs(true_velocity.x * delta)
  69. camera_position.x = global_position.x + offset
  70. elif global_position.x <= camera_position.x + get_viewport_rect().size.x / 4:
  71. if true_velocity.x < -75:
  72. camera_position.x += true_velocity.x * delta / 2
  73. else:
  74. camera_position.x += true_velocity.x * delta
  75. func handle_vertical_scrolling(_delta: float) -> void:
  76. ## VERTICAL MOVEMENT
  77. if global_position.y < camera_position.y and owner.is_on_floor():
  78. camera_position.y = move_toward(camera_position.y, global_position.y, 3)
  79. elif global_position.y < camera_position.y - 64:
  80. camera_position.y = global_position.y + 64
  81. elif global_position.y > camera_position.y + 32:
  82. camera_position.y = global_position.y - 32
  83. func tween_ahead() -> void:
  84. if scrolling == false: return
  85. await get_tree().create_timer(0.25).timeout
  86. var tween = create_tween()
  87. tween.tween_property(self, "camera_position:x", camera_position.x + (32 * cam_direction), 0.25)
  88. func recenter_camera() -> void:
  89. camera_position = global_position
  90. last_position = camera_position
  91. camera_position += camera_offset
  92. do_limits()
  93. camera.global_position = camera_position
  94. func handle_offsets(delta: float) -> void:
  95. var true_velocity = (global_position - last_position) / delta
  96. var true_vel_dir = sign(true_velocity.x)
  97. if owner.velocity.x == 0 or (owner.is_on_wall() and owner.direction == -owner.get_wall_normal().x):
  98. true_vel_dir = 0
  99. true_velocity.x = 0
  100. if Global.current_level.can_backscroll:
  101. if true_vel_dir != 0 and abs(true_velocity.x) > 80:
  102. if abs(camera_position.x - global_position.x) <= 64:
  103. camera_offset.x = move_toward(camera_offset.x, 8 * true_vel_dir, abs(true_velocity.x) / 200)
  104. else:
  105. camera_offset.x = 8
  106. func do_limits() -> void:
  107. camera_right_limit = clamp(Player.camera_right_limit, -256 + (get_viewport().get_visible_rect().size.x), INF)
  108. camera_position.x = clamp(camera_position.x, point_to_camera_limit(-256 - camera_offset.x, -1), point_to_camera_limit(camera_right_limit - camera_offset.x, 1))
  109. camera_position.y = clamp(camera_position.y, point_to_camera_limit_y(Global.current_level.vertical_height, -1), point_to_camera_limit_y(32, 1))
  110. var wall_enabled := true
  111. if is_instance_valid(Global.level_editor):
  112. if Global.level_editor.playing_level == false:
  113. wall_enabled = false
  114. $"../CameraCenterJoint/LeftWall".set_collision_layer_value(1, wall_enabled)
  115. var level_exit = false
  116. if owner.state_machine != null:
  117. level_exit = owner.state_machine.state.name == "LevelExit"
  118. $"../CameraCenterJoint/RightWall".set_collision_layer_value(1, wall_enabled and level_exit == false)
  119. func point_to_camera_limit(point := 0, point_dir := -1) -> float:
  120. return point + ((get_viewport_rect().size.x / 2.0) * -point_dir)
  121. func point_to_camera_limit_y(point := 0, point_dir := -1) -> float:
  122. return point + ((get_viewport_rect().size.y / 2.0) * -point_dir)