giants-godot/player/TPSController.gd

189 lines
5.7 KiB
GDScript

extends Spatial
class_name TPSController
# debug camera
export var reaper_path: NodePath
export var vimp_path: NodePath
export var character_path: NodePath
onready var character: Character = get_node(character_path)
var head: Spatial
var cam: Camera
var default_camera_trans: Transform
var is_in_menu: bool = false
export var FOV = 80.0
export var HUD_scene: PackedScene
onready var HUD: Control
onready var debug_label: Label = $DebugText
var mouse_axis: Vector2 = Vector2.ZERO
export var mouse_sensitivity: float = 10.0
var cursor_no_enemy: Control
var cursor_enemy: Control
func set_character(c: Character):
if cam:
cam.current = false
character = c
cam = character.back_camera
default_camera_trans = cam.transform
head = character.head
cam.fov = FOV
cam.current = true
func _ready():
set_character(character)
if not Engine.editor_hint:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
HUD = HUD_scene.instance()
add_child(HUD)
character.connect("health_changed", self, "update_health")
if HUD.has_node("cursor_enemy"):
cursor_enemy = HUD.get_node("cursor_enemy")
if HUD.has_node("cursor_no_enemy"):
cursor_enemy = HUD.get_node("cursor_no_enemy")
func get_target() -> Dictionary:
var weapon = character.current_weapon
var ray_from = cam.global_transform.origin
var ray_to = cam.global_transform.basis.z * -20000
var space_state = get_world().direct_space_state
var result = space_state.intersect_ray(ray_from, ray_to, [self, weapon])
if not result:
return Globals.create_empty_collision_dictionnary(ray_to)
else:
return result
func _physics_process(delta):
if Engine.editor_hint:
return
debug_label.text = "FPS: " + str(Engine.get_frames_per_second()) + " | Objects: " + str(Performance.get_monitor(Performance.OBJECT_COUNT))
# calculate and export target
var target = get_target()
Globals.target_position = target
# cursor change
if cursor_no_enemy and cursor_enemy:
if target["collider"] and target["collider"] is Entity:
cursor_no_enemy.visible = false
cursor_enemy.visible = true
else:
cursor_enemy.visible = false
cursor_no_enemy.visible = true
# update camera
if character.sprinting:
cam.set_fov(lerp(cam.fov, FOV * 1.2, delta * 8))
else:
cam.set_fov(lerp(cam.fov, FOV, delta * 8))
# head.global_transform.origin = character.global_transform.origin
func camera_rotation() -> void:
if mouse_axis.length() > 0:
var _smoothness := 80
# Get mouse delta
var horizontal: float = -(mouse_axis.x * mouse_sensitivity) / _smoothness
var vertical: float = -(mouse_axis.y * mouse_sensitivity) / _smoothness
mouse_axis = Vector2.ZERO
character.rotate_y(deg2rad(horizontal))
var temp_rot: Vector3 = head.rotation_degrees
temp_rot += Vector3(vertical, 0, 0)
# temp_rot += Vector3(vertical, horizontal, 0)
# clamp vertical rotation
temp_rot.x = clamp(temp_rot.x, -75, 75)
head.rotation_degrees = temp_rot
func _input(event: InputEvent) -> void:
if Engine.editor_hint:
return
if not Globals.process_3d_inputs:
return
if event is InputEventMouseMotion:
mouse_axis = event.relative
if Input.is_action_pressed("camera_front"):
var camera_front_transform = default_camera_trans
camera_front_transform = default_camera_trans.translated(Vector3(5, 0, -5))
camera_front_transform = camera_front_transform.rotated(Vector3.UP, deg2rad(-180))
cam.transform = camera_front_transform
if Input.is_action_just_released("camera_front"):
cam.transform = default_camera_trans
if Input.is_action_just_pressed("inp_fire"):
character.fire_pressed()
if Input.is_action_just_released("inp_fire"):
character.fire_released()
if Input.is_action_just_pressed("weapon_forward"):
character.switch_next_weapon_slot()
if Globals.process_3d_inputs and Input.is_action_just_pressed("ui_cancel"):
var ingame_menu = preload("res://ui/menus/ingame_menu.tscn").instance()
Input.set_mouse_mode(Input.MOUSE_MODE_CONFINED)
add_child(ingame_menu)
ingame_menu.connect("tree_exited", self, "_ingamemenu_closed")
Globals.process_3d_inputs = false
if Input.is_action_just_pressed("camera_reaper"):
set_character(get_node(reaper_path))
if Input.is_action_just_pressed("camera_vimp"):
set_character(get_node(vimp_path))
if Input.is_action_just_pressed("move_jump"):
character.jump()
if Input.is_action_just_pressed("move_sprint"):
character.set_sprint(true)
if Input.is_action_just_released("move_sprint"):
character.set_sprint(false)
func _ingamemenu_closed():
Globals.process_3d_inputs = true
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _process(_delta: float) -> void:
if Engine.editor_hint:
return
if Globals.process_3d_inputs:
camera_rotation()
character.move_axis.x = Input.get_action_strength("move_forward") - Input.get_action_strength("move_backward")
character.move_axis.y = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
update_hud()
func update_hud() -> void:
# for weapon_slot in HUD.find_node("Weapon*"):
# for child in weapon_slot.get_children():
# weapon_slot.remove_child(child)
for weapon in character.weapons:
var weapon_slot = character.get_weapon_slot(weapon)
var hud_weapon_slot = HUD.find_node("Weapon%s" % weapon_slot)
var weapon_icon: Control = weapon.ui_icon
if not weapon_icon.get_parent() == hud_weapon_slot:
hud_weapon_slot.add_child(weapon_icon)
if character.current_weapon == weapon:
hud_weapon_slot.get_node("selected").visible = true
else:
hud_weapon_slot.get_node("selected").visible = false
func update_health() -> void:
var current_health = character.health
var max_health = character.max_health
var hp_percent = current_health/max_health
# UI/hp polygon: 0 means 100% hp, 250 means 0%
var val = 250 - 250*hp_percent
HUD.find_node("hp").texture_offset = Vector2(val, 0)