70 lines
2.0 KiB
GDScript
70 lines
2.0 KiB
GDScript
## Scrolls the camera when the mouse cursor reaches the screen edge.
|
|
## Attach to a Camera2D node. Requires an OrthographicCamera2D or ViewportContainer
|
|
## to determine screen bounds at runtime.
|
|
extends Camera2D
|
|
|
|
## Speed at which the camera scrolls (pixels per second).
|
|
@export var scroll_speed: float = 400.0
|
|
|
|
## Distance from the edge (in pixels) that triggers scrolling.
|
|
@export var edge_margin: float = 40.0
|
|
|
|
## Whether to clamp the camera position to a specific region.
|
|
@export var clamp_enabled: bool = false
|
|
|
|
## Minimum bounds when clamping (in world space).
|
|
@export var clamp_min: Vector2 = Vector2.ZERO
|
|
|
|
## Maximum bounds when clamping (in world space).
|
|
@export var clamp_max: Vector2 = Vector2.ZERO
|
|
|
|
var _screen_rect: Rect2
|
|
|
|
|
|
func _ready() -> void:
|
|
_update_screen_rect()
|
|
var viewport: Viewport = get_viewport()
|
|
if viewport != null:
|
|
viewport.size_changed.connect(_update_screen_rect)
|
|
|
|
|
|
func _process(delta: float) -> void:
|
|
if is_zero_approx(scroll_speed):
|
|
return
|
|
|
|
var mouse_pos: Vector2 = get_viewport().get_mouse_position()
|
|
var scroll_dir: Vector2 = _get_scroll_direction(mouse_pos)
|
|
|
|
if scroll_dir != Vector2.ZERO:
|
|
position += scroll_dir * scroll_speed * delta
|
|
|
|
if clamp_enabled:
|
|
_clamp_position()
|
|
|
|
|
|
func _get_scroll_direction(mouse_pos: Vector2) -> Vector2:
|
|
var direction: Vector2 = Vector2.ZERO
|
|
|
|
if mouse_pos.x < _screen_rect.position.x + edge_margin:
|
|
direction.x -= 1.0
|
|
elif mouse_pos.x > _screen_rect.position.x + _screen_rect.size.x - edge_margin:
|
|
direction.x += 1.0
|
|
|
|
if mouse_pos.y < _screen_rect.position.y + edge_margin:
|
|
direction.y -= 1.0
|
|
elif mouse_pos.y > _screen_rect.position.y + _screen_rect.size.y - edge_margin:
|
|
direction.y += 1.0
|
|
|
|
return direction.normalized()
|
|
|
|
|
|
func _clamp_position() -> void:
|
|
position.x = clampf(position.x, clamp_min.x, clamp_max.x)
|
|
position.y = clampf(position.y, clamp_min.y, clamp_max.y)
|
|
|
|
|
|
func _update_screen_rect() -> void:
|
|
var viewport: Viewport = get_viewport()
|
|
if viewport != null:
|
|
_screen_rect = viewport.get_visible_rect()
|