Add a world model and refactor the controller

This commit is contained in:
2025-01-25 09:03:06 +01:00
parent 51842836ce
commit 1f1f2918c9
14 changed files with 1451 additions and 65 deletions

View File

@ -14,6 +14,7 @@ class_name Player extends CharacterBody3D
@onready var upper_torso_default_position: Vector3 = upper_torso.position
@export var ANIMATION_PLAYER : AnimationPlayer
@onready var body: Node3D = $RealBody
var jumping: bool = false
var mouse_captured: bool = false
var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity")
@ -32,6 +33,10 @@ var is_crouch: bool = false
func _ready() -> void:
$"../MultiplayerSynchronizer".set_multiplayer_authority(str($"..".name).to_int())
# If player is not the current player, we need to add a model
if str($"..".name).to_int() != multiplayer.get_unique_id():
var dummy = ResourceLoader.load("res://scenes/characters/blue/dummy.tscn").instantiate()
add_child(dummy)
enable_camera()
capture_mouse()
#print("I am " + str(multiplayer.get_unique_id()) + "I'm controling " + str($"../MultiplayerSynchronizer".get_multiplayer_authority()))
@ -42,7 +47,8 @@ func _unhandled_input(event: InputEvent) -> void:
if mouse_captured: _rotate_camera()
if Input.is_action_just_pressed("jump"): jumping = true
if Input.is_action_just_pressed("exit"): get_tree().quit()
if Input.is_action_just_pressed("shot"): $UpperTorso/ViewModelCamera.shot()
if str($"..".name).to_int() == multiplayer.get_unique_id():
if Input.is_action_just_pressed("shot"): $UpperTorso/ViewModelCamera.shot()
if Input.is_action_just_pressed("reload"): $Body/UpperTorso/CameraMount/Camera.reload()
if Input.is_action_just_pressed("crouch"): crouch()
if Input.is_action_just_released("crouch"): uncrouch()
@ -66,8 +72,9 @@ func release_mouse() -> void:
mouse_captured = false
func _rotate_camera(sens_mod: float = 1.0) -> void:
character.rotation.y -= look_dir.x * camera_sens * sens_mod
camera.rotation.x = clamp(camera.rotation.x - look_dir.y * camera_sens * sens_mod, -1.5, 1.5)
if str($"..".name).to_int() == multiplayer.get_unique_id():
character.rotation.y -= look_dir.x * camera_sens * sens_mod
camera.rotation.x = clamp(camera.rotation.x - look_dir.y * camera_sens * sens_mod, -1.5, 1.5)
func _handle_joypad_camera_rotation(delta: float, sens_mod: float = 1.0) -> void:
var joypad_dir: Vector2 = Input.get_vector("look_left","look_right","look_up","look_down")
@ -84,7 +91,7 @@ func _walk(delta: float) -> Vector3:
var cur_speed: float
if is_crouch:
cur_speed = speed / 3
#upper_torso.position.y -= 10
#upper_torso.position.y -= 10
else:
cur_speed = speed
if Input.is_action_pressed("silent_walk"):

View File

@ -0,0 +1,159 @@
# ---------------------------------------------------------------------
# This script is supposed to handle character movement logic
# ---------------------------------------------------------------------
class_name PlayerInput extends CharacterBody3D
@export_category("PlayerInput")
const SPEED = 5.0
const JUMP_VELOCITY = 4.5
var mouse_captured: bool = false
@onready var player_synchronizer: MultiplayerSynchronizer = $PlayerSynchronizer
@onready var first_view_camera_mount: Node3D = $FirstPersonCameraMount
@onready var first_view_camera: Camera3D = $FirstPersonCameraMount/Camera
@onready var model_mount: Node3D = $ModelMount
# -- This node is supposed to be spawned per player, and since each
# -- player has an id, it is used for giving a node a name. So we can
# -- use it here to tell a controlled node from the rest models
@onready var owner_id: int = str($".".name).to_int()
var multiplayer_id: int = 0
# -- Character state
var alive: bool = true
func _ready() -> void:
player_synchronizer.set_multiplayer_authority(owner_id)
multiplayer_id = multiplayer.get_unique_id()
# -- Separate logic for player and other models that are controlled
# -- by other players on the server
# -- TODO: If player is alive, it must not be able to see other
# -- cameras, but if player is dead, it must be able to
# -- switch between other players
if _is_current_player():
var err := _add_first_view_model()
if err != OK:
print("Error occured: " + str(err))
_enable_camera()
else:
var err := _add_world_model()
if err != OK:
print("Error occured: " + str(err))
_capture_mouse()
# -- Add a world model to the player, that should be seen by other players
# -- on the server
func _add_world_model() -> Error :
# -- TODO: It should not be hardcoded
var path := "res://scenes/characters/blue/dummy.tscn"
if not ResourceLoader.exists(path):
return ERR_DOES_NOT_EXIST
var scene: PackedScene = ResourceLoader.load(path)
if not scene.can_instantiate():
return ERR_CANT_OPEN
var node: Node3D = scene.instantiate()
model_mount.add_child(node)
return OK
# -- Add the first person view to pthe player
func _add_first_view_model() -> Error :
# -- TODO: It should not be hardcoded
var path := "res://scenes/characters/first_person_view.tscn"
if not ResourceLoader.exists(path):
return ERR_DOES_NOT_EXIST
var scene: PackedScene = ResourceLoader.load(path)
if not scene.can_instantiate():
return ERR_CANT_OPEN
var node: Node3D = scene.instantiate()
first_view_camera.add_child(node)
return OK
func _enable_camera():
first_view_camera.make_current()
func _capture_mouse() -> void:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
mouse_captured = true
func _release_mouse() -> void:
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
mouse_captured = false
# -- Does the peer own the node
func _is_current_player() -> bool:
if owner_id == multiplayer_id:
return true
return false
# ---------------------------------------------------------------------
# -- Input controller
# ---------------------------------------------------------------------
var move_dir: Vector2 # Input direction for movement
var look_dir: Vector2 # Input direction for look/aim
var walk_vel: Vector3 # Walking velocity
var grav_vel: Vector3 # Gravity velocity
var jump_vel: Vector3 # Jumping velocity
@export_range(0.1, 3.0, 0.1) var jump_height: float = 1 # m
@export_range(0.1, 3.0, 0.1, "or_greater") var camera_sens: float = 1
func _unhandled_input(event: InputEvent) -> void:
if _is_current_player():
if event is InputEventMouseMotion:
look_dir = event.relative * 0.001
if mouse_captured: _rotate_camera()
#if Input.is_action_just_pressed("jump"): jumping = true
if Input.is_action_just_pressed("exit"): get_tree().quit()
if Input.is_action_pressed("shot"): _shoot()
#if str($"..".name).to_int() == multiplayer.get_unique_id():
#if Input.is_action_just_pressed("shot"): $UpperTorso/ViewModelCamera.shot()
#if Input.is_action_just_pressed("reload"): $Body/UpperTorso/CameraMount/Camera.reload()
func _rotate_camera(sens_mod: float = 1.0) -> void:
#if str($"..".name).to_int() == multiplayer.get_unique_id():
rotation.y -= look_dir.x * camera_sens * sens_mod
first_view_camera_mount.rotation.x = clamp(first_view_camera_mount.rotation.x - look_dir.y * camera_sens * sens_mod, -1.5, 1.5)
func _physics_process(delta: float) -> void:
# Add the gravity.
if not is_on_floor():
velocity += get_gravity() * delta
# Handle jump.
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = JUMP_VELOCITY
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
#var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
# -- It shouldn't be possible to change direction during the jumps
if is_on_floor():
var input_dir := Input.get_vector("move_left", "move_right", "move_forward", "move_backwards")
var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if direction:
velocity.x = direction.x * SPEED
velocity.z = direction.z * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
velocity.z = move_toward(velocity.z, 0, SPEED)
move_and_slide()
# -- TODO: It shouldn't be hardcoded
var bullet = load("res://scenes/weapon/bullet.tscn")
@onready var shooting_raycast: RayCast3D = $FirstPersonCameraMount/RayCast3D
@onready var bullet_starting_point: Node3D = $FirstPersonCameraMount/BulletStartingPoint
func _shoot():
print("shooting")
var root := get_tree().get_root()
#if !gun_anim.is_playing():
#gun_anim.play("Shoot")
var node: Node3D = bullet.instantiate()
node.position = bullet_starting_point.global_position
node.transform.basis = bullet_starting_point.global_transform.basis
root.add_child(node)