Godot-RTS-Template/Core/player.gd

138 lines
5.4 KiB
GDScript

extends Node3D
class_name Player
#region Declarations
@export_category("Speed")
@onready var move_speed: float = ProjectSettings.get_setting("game/controls/camera_move_speed",20.0)
@onready var zoom_speed: float = ProjectSettings.get_setting("game/controls/camera_zoom_speed",20.0)
@export_category("Limits")
@export_range(-10,10,1) var zoom_min: float = -4
@export_range(11,50,1) var zoom_max: float = 20
@export_range(0,0.95,0.01) var zoom_speed_damp: float = ProjectSettings.get_setting("game/controls/camera_zoom_damp",0.85)
@export_range(0,32,4) var edge_scrolling_margin: int = ProjectSettings.get_setting("game/controls/edge_scrolling_margin",8)
@onready var edge_scrolling_speed: float = ProjectSettings.get_setting("game/controls/edge_scrolling_speed",25.0)
@onready var cam: Camera3D = %camera_player
var zoom_direction: float = 0.0 # if different than zero, zoom is happening
var move_disabled:bool = false
var zoom_disabled:bool = false
var edge_scroll_disabled:bool = ProjectSettings.get_setting("game/controls/edge_scrolling_disabled",false)
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
#endregion
func _ready():
Input.mouse_mode = Input.MOUSE_MODE_CONFINED # Maybe should be moved in a better script
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
cam_move(delta)
cam_zoom(delta)
cam_edge_scroll(delta)
cam_rotation(delta)
func _notification(what: int):
if what == NOTIFICATION_APPLICATION_FOCUS_OUT:
print("focus out!")
#get_tree().paused = true
edge_scroll_disabled = true
move_disabled = true
if what == NOTIFICATION_APPLICATION_FOCUS_IN:
print("focus in!")
#get_tree().paused = false
edge_scroll_disabled = false
move_disabled = false
if what == NOTIFICATION_WM_MOUSE_ENTER:
print("focus in!")
func _unhandled_input(event: InputEvent) -> void:
if event.is_action("scroll_up"):
zoom_direction = -1
print("scroll")
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
if event.is_action_released("rotation_mode"):
rotation_mode = false
Input.mouse_mode = Input.MOUSE_MODE_CONFINED
if event.as_text() == "Escape":
get_tree().quit()
#region Getter
func get_mouse_position() -> Vector2:
return get_viewport().get_mouse_position()
## multiplicator for movement speed, based on zoom level
## [br][br]
## Return a remapped float between [param _min] and [param _max]
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:
if move_disabled:return
var velocity_direction := Vector3.ZERO
if Input.is_action_pressed("cam_backward"): velocity_direction -= transform.basis.x
if Input.is_action_pressed("cam_forward"): velocity_direction += transform.basis.x
if Input.is_action_pressed("cam_left"): velocity_direction -= transform.basis.z
if Input.is_action_pressed("cam_right"): velocity_direction += transform.basis.z
position.x += velocity_direction.normalized().x * delta * move_speed * get_zoom_factor()
position.z += velocity_direction.normalized().z * delta * move_speed * get_zoom_factor()
## Controls the zoom of the player camera
## [br]
## [param zoom_direction] control the direction.
## 0.0 means no zoom. Use 1.0 for moving toward the floor
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:
print("new zoom : ", new_zoom, " because zoom_direction = ",zoom_direction)
cam.position.z = new_zoom
zoom_direction *= zoom_speed_damp #Smooth the deceleration
func cam_edge_scroll(delta:float) -> void:
if edge_scroll_disabled:return
var current_viewport = get_viewport()
var pan_direction := Vector2(0,0) #Edge scrolling to bottom left by default, changing that if needed
var viewport_rectange := Rect2i(current_viewport.get_visible_rect())
var viewport_size := viewport_rectange.size
var mouse_position = get_mouse_position()
# X PAN
if (mouse_position.x < edge_scrolling_margin or (mouse_position.x > viewport_size.x - edge_scrolling_margin)):
pan_direction.x = 1 if (mouse_position.x > viewport_size.x/2) else -1 # detect if we are in the half of the screen or not
# Y PAN
if (mouse_position.y < edge_scrolling_margin or (mouse_position.y > viewport_size.y - edge_scrolling_margin)):
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()
translate_object_local(Vector3(pan_vector.y,0,pan_vector.x))
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
#endregion