From 30e7ebc927582b1bd9441ebf937011a65771be74 Mon Sep 17 00:00:00 2001 From: lucastucious Date: Mon, 21 Jul 2025 17:46:53 +0200 Subject: [PATCH] smoothing camera movement --- Core/cursor_behaviour.gd | 19 +++++++++++++++ Core/player.gd | 52 +++++++++++++++++++++++++++++++--------- Core/player.tscn | 2 ++ project.godot | 12 ++++++++++ 4 files changed, 74 insertions(+), 11 deletions(-) diff --git a/Core/cursor_behaviour.gd b/Core/cursor_behaviour.gd index 46768bf..f6bf98c 100644 --- a/Core/cursor_behaviour.gd +++ b/Core/cursor_behaviour.gd @@ -1,5 +1,14 @@ extends Node ## Handle all the cursor appareance related stuff. +const nav_e = preload("res://Packs/Kenney-cursors/Outline/navigation_e.svg") +const nav_n = preload("res://Packs/Kenney-cursors/Outline/navigation_n.svg") +const nav_ne = preload("res://Packs/Kenney-cursors/Outline/navigation_ne.svg") +const nav_nw = preload("res://Packs/Kenney-cursors/Outline/navigation_nw.svg") +const nav_s = preload("res://Packs/Kenney-cursors/Outline/navigation_s.svg") +const nav_se = preload("res://Packs/Kenney-cursors/Outline/navigation_se.svg") +const nav_sw = preload("res://Packs/Kenney-cursors/Outline/navigation_sw.svg") +const nav_w = preload("res://Packs/Kenney-cursors/Outline/navigation_w.svg") + # Called when the node enters the scene tree for the first time. func _ready() -> void: @@ -9,3 +18,13 @@ func _ready() -> void: # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: pass + + +func _on_player_root_cursor_edge_scrolling(direction: Vector2) -> void: + print("panning vector", direction) + return + if direction.length() > 0: + if direction.x > 0: + Input.set_custom_mouse_cursor(nav_e) + else: + Input.set_custom_mouse_cursor(nav_ne) diff --git a/Core/player.gd b/Core/player.gd index 17f101b..27129f7 100644 --- a/Core/player.gd +++ b/Core/player.gd @@ -14,6 +14,8 @@ class_name Player @onready var cam: Camera3D = %camera_player +var mouse_velocity + var zoom_direction: float = 0.0 # if different than zero, zoom is happening var move_disabled:bool = false var zoom_disabled:bool = false @@ -21,7 +23,12 @@ var edge_scroll_disabled:bool = ProjectSettings.get_setting("game/controls/edge_ var invert_rotation_x:bool = ProjectSettings.get_setting("game/controls/invert_cam_rotation_x",false) var invert_rotation_y:bool = ProjectSettings.get_setting("game/controls/invert_cam_rotation_y",false) var rotation_mode:bool = false -var rotation_damp:float = 0.01 +@export_range(0,1,0.01) var rotation_speed_x:float = ProjectSettings.get_setting("game/controls/cam_rotation_speed_x",0.5) +@export_range(0,1,0.01) var rotation_speed_y:float = ProjectSettings.get_setting("game/controls/cam_rotation_speed_y",0.5) + +@export_category("Signals") +signal cursor_edge_scrolling(direction:Vector2) + #endregion @@ -34,7 +41,6 @@ func _process(delta: float) -> void: cam_move(delta) cam_zoom(delta) cam_edge_scroll(delta) - cam_rotation(delta) func _notification(what: int): @@ -52,6 +58,15 @@ func _notification(what: int): print("focus in!") +func _input(event: InputEvent) -> void: + if event is InputEventMouseMotion and rotation_mode: + print("Mouse Motion at: ", event.screen_relative) + mouse_velocity = event.screen_relative + cam_rotation(event.screen_relative) + else: + mouse_velocity = Vector2(0,0) + + func _unhandled_input(event: InputEvent) -> void: if event.is_action("scroll_up"): zoom_direction = -1 @@ -59,12 +74,24 @@ func _unhandled_input(event: InputEvent) -> void: if event.is_action("scroll_down"): zoom_direction = 1 if event.is_action_pressed("rotation_mode"): - rotation_mode = true Input.mouse_mode = Input.MOUSE_MODE_CAPTURED + mouse_velocity = Vector2(0,0) + rotation_mode = true + if event.is_action_released("rotation_mode"): rotation_mode = false Input.mouse_mode = Input.MOUSE_MODE_CONFINED - if event.as_text() == "Escape": + if event.is_action_pressed("DEBUG-quit"): + quit_game() + + +func quit_game() -> void: + var quit_label = Label.new() + quit_label.text = "Quitting game ..." + quit_label.uppercase = true + quit_label.add_child(get_tree().current_scene) + Input.mouse_mode = Input.MOUSE_MODE_HIDDEN + get_tree().root.propagate_notification(NOTIFICATION_WM_CLOSE_REQUEST) get_tree().quit() @@ -79,8 +106,9 @@ func get_mouse_position() -> Vector2: func get_zoom_factor(_min:=0.1,_max:=2.0) -> float: return remap(cam.position.z,zoom_min,zoom_max,_min,_max) - #endregion + + #region Movement ## Controls the movement of the player camera func cam_move(delta:float) -> void: @@ -104,7 +132,7 @@ func cam_zoom(delta:float) -> void: if zoom_disabled:return var new_zoom: float = clamp(cam.position.z + (zoom_speed * zoom_direction * delta),zoom_min,zoom_max) - if new_zoom != cam.position.z: + if new_zoom != cam.position.z and abs(zoom_direction) > 0.001: print("new zoom : ", new_zoom, " because zoom_direction = ",zoom_direction) cam.position.z = new_zoom zoom_direction *= zoom_speed_damp #Smooth the deceleration @@ -127,12 +155,14 @@ func cam_edge_scroll(delta:float) -> void: pan_direction.y = 1 if (mouse_position.y < viewport_size.y/2) else -1 # detect if we are in the half of the screen or not var pan_vector:= Vector2(pan_direction.x,pan_direction.y) * delta * edge_scrolling_speed * get_zoom_factor() + if pan_vector.length() > 0: + translate_object_local(Vector3(pan_vector.y,0,pan_vector.x)) + #print("panning", pan_vector) - translate_object_local(Vector3(pan_vector.y,0,pan_vector.x)) + cursor_edge_scrolling.emit(pan_direction.normalized()) -func cam_rotation(delta:float) -> void: - if rotation_mode: - rotation.y += Input.get_last_mouse_velocity().x * delta * rotation_damp * (-1 if invert_rotation_x else 1) #TODO: REMOVE MAGIC NUMBERS - %camera_rot.rotation.z = clamp(%camera_rot.rotation.z + Input.get_last_mouse_velocity().y * rotation_damp * delta * (-1 if invert_rotation_y else 1),-0.75,0.35) #TODO: REMOVE MAGIC NUMBERS +func cam_rotation(mouse_relative:Vector2) -> void: + rotation.y += mouse_velocity.x * get_process_delta_time() * rotation_speed_x * (-1 if invert_rotation_x else 1) + %camera_rot.rotation.z = clamp(%camera_rot.rotation.z + (mouse_relative.y * get_process_delta_time() * rotation_speed_y) * (-1 if invert_rotation_y else 1),-0.75,0.35) #= clamp(desired_rot.x,-0.75,0.35) #TODO: REMOVE MAGIC NUMBERS #endregion diff --git a/Core/player.tscn b/Core/player.tscn index e6d5fb5..4176670 100644 --- a/Core/player.tscn +++ b/Core/player.tscn @@ -35,3 +35,5 @@ mesh = SubResource("SphereMesh_ipmo0") [node name="CursorComponent" type="Node" parent="."] script = ExtResource("2_ipmo0") + +[connection signal="cursor_edge_scrolling" from="." to="CursorComponent" method="_on_player_root_cursor_edge_scrolling"] diff --git a/project.godot b/project.godot index e67c405..02de14b 100644 --- a/project.godot +++ b/project.godot @@ -13,9 +13,11 @@ config_version=5 config/name="Kenshi2" config/tags=PackedStringArray("games") run/main_scene="uid://dnmetcwb14svi" +config/project_settings_override="settings.cfg" config/features=PackedStringArray("4.5", "Forward Plus") config/icon="res://icon.svg" + [display] mouse_cursor/custom_image="uid://dp4ed16rb1754" @@ -35,6 +37,11 @@ folder_colors={ controls/camera_zoom_speed=20.0 controls/camera_move_speed=20.0 +controls/cam_rotation_speed_x=0.19999999999708962 +controls/cam_rotation_speed_y=0.19999999999708962 +controls/invert_cam_rotation_x=false +controls/invert_cam_rotation_y=true + [input] @@ -80,6 +87,11 @@ rotation_mode={ , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194326,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) ] } +DEBUG-quit={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} [physics]