extends Camera2D @export var target_res : Vector2 = Vector2(480, 270) @export var target_zoom : float = 1 @export var cam_speed : float = 5.0 @export var min_speed : float = 0.1 @export var ui_layer : CanvasLayer # --- NEW VARIABLE --- # 0.0 = no movement, 0.5 = camera moves halfway to mouse, 1.0 = camera centers on mouse @export_range(0.0, 1.0) var mouse_look_strength : float = 0.15 # -------------------- @export var shake_decay : float = 5.0 @export var max_offset : Vector2 = Vector2(10, 10) var pixel_material : ShaderMaterial var scaling : Vector2 var actual_pos : Vector2 var shake_trauma : float = 0.0 func _ready(): # Safety check to prevent crash if node is missing if has_node("Pixelator"): pixel_material = get_node("Pixelator").material get_viewport().size_changed.connect(_on_viewport_resized) EventBus.player_dmg.connect(_on_player_dmg) EventBus.screenshake.connect(_on_screenshake) _on_viewport_resized() func _fract(x : Vector2) -> Vector2: return x - floor(x) func _on_player_dmg(): # Apply a default punchy shake when hit add_shake(0.5) func _on_screenshake(intensity: float): add_shake(intensity) func add_shake(amount: float): shake_trauma = clamp(shake_trauma + amount, 0.0, 1.0) func _apply_shake(): # Squaring trauma makes the shake feel more organic (stronger at start, tapers off) var amount = pow(shake_trauma, 2) var offset = Vector2( max_offset.x * amount * randf_range(-1, 1), max_offset.y * amount * randf_range(-1, 1) ) # Apply floor to keep the shake aligned with your pixel grid global_position = floor(actual_pos + offset) func _on_viewport_resized(): var viewport_res : Vector2 = get_viewport().get_visible_rect().size scaling = Vector2(viewport_res.x / target_res.x, viewport_res.y / target_res.y) if has_node("Pixelator"): var pixel_rect : ColorRect = get_node("Pixelator") pixel_rect.position = -target_res / 2. pixel_rect.size = target_res zoom = scaling * target_zoom if ui_layer: ui_layer.scale = zoom EventBus.debug_print.emit("new scaling: " + str(scaling)) func _process(delta : float): var parent_pos : Vector2 = get_parent().global_position # --- NEW MOUSE LOOK LOGIC --- var mouse_pos = get_viewport().get_mouse_position() var vp_size = get_viewport().get_visible_rect().size var center = vp_size / 2.0 # Calculate how far mouse is from center var offset_from_center = mouse_pos - center # Apply strength factor offset_from_center *= mouse_look_strength # Convert screen pixels to world units by dividing by the current scaling/zoom # (We guard against division by zero just in case) if scaling.x != 0 and scaling.y != 0: var world_offset = offset_from_center / scaling parent_pos += world_offset # --------------------------- var dist := actual_pos.distance_to(parent_pos) var speed : float = max(min_speed, dist * cam_speed) * delta actual_pos = actual_pos.move_toward(parent_pos, speed) if shake_trauma > 0: shake_trauma = max(shake_trauma - shake_decay * delta, 0) _apply_shake() else: global_position = floor(actual_pos) var sub_pixels : Vector2 = floor(_fract(actual_pos) * scaling) if pixel_material: pixel_material.set_shader_parameter("cam_pos", sub_pixels) pixel_material.set_shader_parameter("scaling", scaling)