diff --git a/game/scenes/player.gd b/game/scenes/player.gd index 322338e..de8ed9f 100644 --- a/game/scenes/player.gd +++ b/game/scenes/player.gd @@ -1,25 +1,25 @@ -extends RigidBody3D -# Initially I used a CharacterBody3D, however, I wanted the player to bounce off -# other objects in the environment and that would have required manual handling -# of collisions. So that's why we're using a RigidBody3D instead. - -const MOVE_SPEED := 8.0 -const ACCELLERATION := 30.0 -const DECELLERATION := 40.0 -const JUMP_SPEED := 4.0 -const MAX_NUMBER_OF_JUMPS := 2 - -const MIN_FOV := 10 -const MAX_FOV := 180 -const ZOOM_FACTOR := 1.1 # Zoom out when >1, in when < 1 -var mouse_sensitivity := 0.005 -var rotation_x := 0.0 -var rotation_y := 0.0 -var cameraMoveMode := false -var current_number_of_jumps := 0 -var _pending_mouse_delta := Vector2.ZERO -var _last_move_forward := Vector3(0, 0, 1) -var _last_move_right := Vector3(1, 0, 0) +extends RigidBody3D +# Initially I used a CharacterBody3D, however, I wanted the player to bounce off +# other objects in the environment and that would have required manual handling +# of collisions. So that's why we're using a RigidBody3D instead. + +const MOVE_SPEED := 8.0 +const SPRINT_MOVE_SPEED :=13 +const ACCELLERATION := 30.0 +const DECELLERATION := 40.0 +const JUMP_SPEED := 4.0 +const MAX_NUMBER_OF_JUMPS := 2 +const MIN_FOV := 10 +const MAX_FOV := 180 +const ZOOM_FACTOR := 1.1 # Zoom out when >1, in when < 1 +var mouse_sensitivity := 0.005 +var rotation_x := 0.0 +var rotation_y := 0.0 +var cameraMoveMode := false +var current_number_of_jumps := 0 +var _pending_mouse_delta := Vector2.ZERO +var _last_move_forward := Vector3(0, 0, 1) +var _last_move_right := Vector3(1, 0, 0) var _camera_offset_local := Vector3.ZERO var _camera_yaw := 0.0 var _camera_pitch := 0.0 @@ -37,40 +37,42 @@ var _jump_triggered := false @export var anim_idle_name := "Idle" @export var anim_walk_name := "Walk" @export var anim_jump_name := "Jump" +@export var anim_run_name := "Run" @export var anim_walk_speed_threshold := 0.25 +@export var anim_sprint_speed_threshold := 10.0 var jump_sound = preload("res://assets/audio/jump.ogg") var audio_player = AudioStreamPlayer.new() - -@export var camera_path: NodePath -@onready var cam: Camera3D = get_node(camera_path) if camera_path != NodePath("") else null -@export var phone_path: NodePath -@onready var phone: CanvasLayer = get_node(phone_path) if phone_path != NodePath("") else null -var phone_visible := false - + +@export var camera_path: NodePath +@onready var cam: Camera3D = get_node(camera_path) if camera_path != NodePath("") else null +@export var phone_path: NodePath +@onready var phone: CanvasLayer = get_node(phone_path) if phone_path != NodePath("") else null +var phone_visible := false + func _ready() -> void: - axis_lock_angular_x = true - axis_lock_angular_z = true - angular_damp = 6.0 - contact_monitor = true - max_contacts_reported = 4 - add_child(audio_player) - audio_player.stream = jump_sound - audio_player.volume_db = -20 + axis_lock_angular_x = true + axis_lock_angular_z = true + angular_damp = 6.0 + contact_monitor = true + max_contacts_reported = 4 + add_child(audio_player) + audio_player.stream = jump_sound + audio_player.volume_db = -20 if cam: - _camera_offset_local = cam.transform.origin - _camera_pitch = cam.rotation.x - _camera_yaw = global_transform.basis.get_euler().y - cam.set_as_top_level(true) - cam.global_position = global_position + (Basis(Vector3.UP, _camera_yaw) * _camera_offset_local) - cam.global_rotation = Vector3(_camera_pitch, _camera_yaw, 0.0) - var move_basis := cam.global_transform.basis if cam else global_transform.basis - var forward := move_basis.z - var right := move_basis.x - forward.y = 0.0 - right.y = 0.0 - if forward.length() > 0.0001: - _last_move_forward = forward.normalized() + _camera_offset_local = cam.transform.origin + _camera_pitch = cam.rotation.x + _camera_yaw = global_transform.basis.get_euler().y + cam.set_as_top_level(true) + cam.global_position = global_position + (Basis(Vector3.UP, _camera_yaw) * _camera_offset_local) + cam.global_rotation = Vector3(_camera_pitch, _camera_yaw, 0.0) + var move_basis := cam.global_transform.basis if cam else global_transform.basis + var forward := move_basis.z + var right := move_basis.x + forward.y = 0.0 + right.y = 0.0 + if forward.length() > 0.0001: + _last_move_forward = forward.normalized() if right.length() > 0.0001: _last_move_right = right.normalized() _vehicle_collision_layer = collision_layer @@ -81,56 +83,61 @@ func _integrate_forces(state): linear_velocity = Vector3.ZERO return if cameraMoveMode and _pending_mouse_delta != Vector2.ZERO: - rotation_x -= _pending_mouse_delta.y * mouse_sensitivity - rotation_y -= _pending_mouse_delta.x * mouse_sensitivity - rotation_x = clamp(rotation_x, deg_to_rad(-90), deg_to_rad(90)) # Prevent flipping - _camera_pitch = rotation_x - rotation.y = rotation_y - _pending_mouse_delta = Vector2.ZERO - - # Input as 2D vector - var input2v := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") - - if Input.is_action_just_pressed("player_phone"): - phone_visible = !phone_visible - if phone: - phone.visible = phone_visible - - # Camera based movement - var forward := Vector3.FORWARD * -1.0 - var right := Vector3.RIGHT - if cam: - forward = cam.global_transform.basis.z - right = cam.global_transform.basis.x - # Project onto ground plane so looking up/down doesn't kill movement. - forward.y = 0.0 - right.y = 0.0 - if forward.length() > 0.0001: - forward = forward.normalized() - _last_move_forward = forward - else: - forward = _last_move_forward - if right.length() > 0.0001: - right = right.normalized() - _last_move_right = right - else: - right = _last_move_right - - var dir := (right * input2v.x + forward * input2v.y).normalized() - var target_v := dir * MOVE_SPEED - - var ax := ACCELLERATION if dir != Vector3.ZERO else DECELLERATION - linear_velocity.x = move_toward(linear_velocity.x, target_v.x, ax * state.step) - linear_velocity.z = move_toward(linear_velocity.z, target_v.z, ax * state.step) - - # Jump Logic - var on_floor = false - for i in state.get_contact_count(): - var normal = state.get_contact_local_normal(i) - if normal.y > 0.5: - on_floor = true - break - + rotation_x -= _pending_mouse_delta.y * mouse_sensitivity + rotation_y -= _pending_mouse_delta.x * mouse_sensitivity + rotation_x = clamp(rotation_x, deg_to_rad(-90), deg_to_rad(90)) # Prevent flipping + _camera_pitch = rotation_x + rotation.y = rotation_y + _pending_mouse_delta = Vector2.ZERO + + # Input as 2D vector + var input2v := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") + + if Input.is_action_just_pressed("player_phone"): + phone_visible = !phone_visible + if phone: + phone.visible = phone_visible + + # Camera based movement + var forward := Vector3.FORWARD * -1.0 + var right := Vector3.RIGHT + if cam: + forward = cam.global_transform.basis.z + right = cam.global_transform.basis.x + # Project onto ground plane so looking up/down doesn't kill movement. + forward.y = 0.0 + right.y = 0.0 + if forward.length() > 0.0001: + forward = forward.normalized() + _last_move_forward = forward + else: + forward = _last_move_forward + if right.length() > 0.0001: + right = right.normalized() + _last_move_right = right + else: + right = _last_move_right + + var dir := (right * input2v.x + forward * input2v.y).normalized() + + var target_v := dir * MOVE_SPEED + + # Sprinting + if Input.is_key_pressed(KEY_SHIFT): + target_v = dir * SPRINT_MOVE_SPEED + + var ax := ACCELLERATION if dir != Vector3.ZERO else DECELLERATION + linear_velocity.x = move_toward(linear_velocity.x, target_v.x, ax * state.step) + linear_velocity.z = move_toward(linear_velocity.z, target_v.z, ax * state.step) + + # Jump Logic + var on_floor = false + for i in state.get_contact_count(): + var normal = state.get_contact_local_normal(i) + if normal.y > 0.5: + on_floor = true + break + if Input.is_action_just_pressed("ui_accept") and (on_floor or current_number_of_jumps == 1): current_number_of_jumps = (current_number_of_jumps + 1) % 2 linear_velocity.y = JUMP_SPEED @@ -147,31 +154,31 @@ func _integrate_forces(state): _update_animation(on_floor, state.linear_velocity) _jump_triggered = false - + func _input(event): if _in_vehicle: return if event is InputEventMouseButton: - if event.button_index == MOUSE_BUTTON_MIDDLE: - if event.pressed: - cameraMoveMode = true - Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) - else: - cameraMoveMode = false - Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) - - if event is InputEventMouseMotion and cameraMoveMode: - _pending_mouse_delta += event.relative - - if event is InputEventMouseButton and event.pressed: - if event.button_index == MOUSE_BUTTON_WHEEL_UP: - zoom_camera(1.0 / ZOOM_FACTOR) # Zoom in - elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN: - zoom_camera(ZOOM_FACTOR) # Zoom out - + if event.button_index == MOUSE_BUTTON_MIDDLE: + if event.pressed: + cameraMoveMode = true + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + else: + cameraMoveMode = false + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + + if event is InputEventMouseMotion and cameraMoveMode: + _pending_mouse_delta += event.relative + + if event is InputEventMouseButton and event.pressed: + if event.button_index == MOUSE_BUTTON_WHEEL_UP: + zoom_camera(1.0 / ZOOM_FACTOR) # Zoom in + elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN: + zoom_camera(ZOOM_FACTOR) # Zoom out + if event.is_action_pressed("player_light"): _flashlight.visible = !_flashlight.visible - + func zoom_camera(factor): var new_fov = cam.fov * factor cam.fov = clamp(new_fov, MIN_FOV, MAX_FOV) @@ -188,6 +195,10 @@ func _update_animation(on_floor: bool, velocity: Vector3) -> void: if _anim_player.current_animation != anim_jump_name: _anim_player.play(anim_jump_name) return + if on_floor and horizontal_speed > anim_sprint_speed_threshold and _anim_player.has_animation(anim_run_name): + if _anim_player.current_animation != anim_walk_name: + _anim_player.play(anim_walk_name) + return if horizontal_speed > anim_walk_speed_threshold and _anim_player.has_animation(anim_walk_name): if _anim_player.current_animation != anim_walk_name: _anim_player.play(anim_walk_name) @@ -233,4 +244,3 @@ func exit_vehicle(exit_point: Node3D, vehicle_camera: Camera3D) -> void: vehicle_camera.current = false if cam: cam.current = true -