maxgame/addons/popochiu/engine/objects/popochiu_main_camera.gd
2025-07-17 01:49:18 -04:00

123 lines
4 KiB
GDScript

class_name PopochiuMainCamera
extends Camera2D
## Takes in charge of the camera used by Popochiu.
var is_shaking := false
var _camera_shake_amount := 15.0
var _shake_timer := 0.0
@onready var tween: Tween = null
@onready var default_limits := {
left = limit_left,
right = get_viewport().get_visible_rect().end.x,
top = limit_top,
bottom = get_viewport().get_visible_rect().end.y
}
#region Godot ######################################################################################
func _process(delta: float) -> void:
if is_shaking:
_shake_timer -= delta
offset = Vector2.ZERO + Vector2(
randf_range(-1.0, 1.0) * _camera_shake_amount,
randf_range(-1.0, 1.0) * _camera_shake_amount
)
if _shake_timer <= 0.0:
stop_shake()
elif (
is_instance_valid(PopochiuUtils.c.camera_owner)
and PopochiuUtils.c.camera_owner.is_inside_tree()
):
position = (
PopochiuUtils.c.camera_owner.position_stored
if PopochiuUtils.c.camera_owner.position_stored
else PopochiuUtils.c.camera_owner.position
)
#endregion
#region Public #####################################################################################
## Changes the main camera's offset by [param offset] pixels. This method is intended to be used
## inside a [method queue] of instructions.
func queue_change_offset(offset := Vector2.ZERO) -> Callable:
return func (): await change_offset(offset)
## Changes the main camera's offset by [param offset] pixels. Useful when zooming the camera.
func change_offset(offset := Vector2.ZERO) -> void:
offset = offset
await get_tree().process_frame
## Makes the camera shake with [param strength] during [param duration] seconds. This method is
## intended to be used inside a [method queue] of instructions.
func queue_shake(strength := 1.0, duration := 1.0) -> Callable:
return func (): await shake(strength, duration)
## Makes the camera shake with [param strength] during [param duration] seconds.
func shake(strength := 1.0, duration := 1.0) -> void:
_camera_shake_amount = strength
_shake_timer = duration
is_shaking = true
await get_tree().create_timer(duration).timeout
## Makes the camera shake with [param strength] during [param duration] seconds without blocking
## execution (that means it runs in the background). This method is intended to be used inside a
## [method queue] of instructions.
func queue_shake_bg(strength := 1.0, duration := 1.0) -> Callable:
return func (): await shake_bg(strength, duration)
## Makes the camera shake with [param strength] during [param duration] seconds without blocking
## execution (that means it runs in the background).
func shake_bg(strength := 1.0, duration := 1.0) -> void:
_camera_shake_amount = strength
_shake_timer = duration
is_shaking = true
await get_tree().process_frame
## Changes the camera zoom. If [param target] is greater than [code]Vector2(1, 1)[/code] the camera
## will [b]zoom out[/b], smaller values will make it [b]zoom in[/b]. The effect will last
## [param duration] seconds. This method is intended to be used inside a [method queue] of
## instructions.
func queue_change_zoom(target := Vector2.ONE, duration := 1.0) -> Callable:
return func (): await change_zoom(target, duration)
## Changes the camera zoom. If [param target] is greater than [code]Vector2(1, 1)[/code] the camera
## will [b]zoom out[/b], smaller values will make it [b]zoom in[/b]. The effect will last
## [param duration] seconds.
func change_zoom(target := Vector2.ONE, duration := 1.0) -> void:
if is_instance_valid(tween) and tween.is_running():
tween.kill()
tween = create_tween().set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)
tween.tween_property(self, "zoom", target, duration).from_current()
await tween.finished
## Makes the camera stop shaking.
func stop_shake() -> void:
is_shaking = false
offset = Vector2.ZERO
_shake_timer = 0.0
## Restores the limits of the camera to their default values
func restore_default_limits() -> void:
limit_left = default_limits.left
limit_right = default_limits.right
limit_top = default_limits.top
limit_bottom = default_limits.bottom
#endregion