X-Git-Url: http://git.purplebirdman.com/baabarian.git/blobdiff_plain/526b0a508cd476fa750b479e59045bd253ca2949..48a972450ae342fd7a4e635b3be6b157432d000d:/player/player.gd diff --git a/player/player.gd b/player/player.gd index 7b988f5..84657ec 100644 --- a/player/player.gd +++ b/player/player.gd @@ -15,10 +15,10 @@ class_name Player @export var hard_landing_limit := 10.0 @export_group("Physics") -@export var push_force := 10 +@export var push_force := 5.0 @export_group("Camera") -@export_range(1.0, 10.0) var camera_distance := 2.5 +@export_range(1.0, 10.0) var camera_distance := 2.0 @export_range(0.0, 1.0) var mouse_sensitivity := 0.15 @export_range(0.0, 1.0) var mouse_sensitivity_x := 1.0 @export_range(0.0, 1.0) var mouse_sensitivity_y := 0.5 @@ -29,24 +29,31 @@ class_name Player @onready var _debug: CanvasLayer = %debug @onready var _camera_pivot: Node3D = %camera_pivot @onready var _camera: Camera3D = %camera +@onready var _camera_spring: SpringArm3D = %spring @onready var _skin: AnimatedSkin = %skin +@onready var _dust: GPUParticles3D = %dust var _last_movement_direction := rotation +var _floor_normal := Vector3.ONE var _camera_input_direction := Vector2.ZERO enum {CAMERA_MOUSE_INPUT, CAMERA_JOYSTICK_INPUT} var _camera_input_method := CAMERA_MOUSE_INPUT var _idle_time: float = 0.0 -var _player_speed: float = walk_speed +var _player_speed: float = 0 func _ready() -> void: - $camera_pivot/SpringArm3D.spring_length = camera_distance _debug.draw.add_vector(self, "velocity", 1, 1, Color(0,1,0,1)) + _debug.draw.add_vector(self, "_floor_normal", 1, 1, Color(0, 0, 1, 1)) _debug.draw.add_vector(self, "_last_movement_direction", 1, 1, Color(1,0,0,1)) _debug.stats.add_property(self, "velocity", "length") _debug.stats.add_property(self, "_idle_time", "round") + + _camera_spring.spring_length = camera_distance + _player_speed = jog_speed + _skin.set_grounded() func _physics_process(delta: float) -> void: @@ -71,12 +78,14 @@ func _unhandled_input(event: InputEvent) -> void: func _input(event: InputEvent): if event.is_action_pressed("player_run"): - _player_speed = jog_speed - elif event.is_action_released("player_run"): _player_speed = walk_speed + elif event.is_action_released("player_run"): + _player_speed = jog_speed if event.is_action_pressed("player_attack") and velocity.length() > jog_speed * .75: _player_speed = charge_speed + elif event.is_action_released("player_attack"): + _player_speed = jog_speed # Get the XZ input direction based on player's input relative to the camera @@ -100,60 +109,76 @@ func _process_camera(delta: float) -> void: # reset mouse movement vector if mouse input if _camera_input_method == CAMERA_MOUSE_INPUT: _camera_input_direction = Vector2.ZERO + + # change spring length depending on player speed + _camera_spring.spring_length = lerp( + _camera_spring.spring_length, camera_distance + velocity.length() / 4, delta + ) func _process_player_on_floor(delta: float): var move_direction := _get_player_move_direction() # if we're not stuck, then it's okay to set the velocity - var floor_normal := move_direction.angle_to(get_floor_normal() * Vector3(1, 0, 1)) + 1 - velocity = velocity.move_toward(move_direction * (_player_speed + 1 / floor_normal * 20), acceleration * delta) + _floor_normal = get_floor_normal() + var ground_angle := move_direction.angle_to(_floor_normal * Vector3(1, 0, 1)) + #print(str(ground_angle)) + velocity = velocity.move_toward(move_direction * (_player_speed + ground_angle), acceleration * delta) var movement_speed := Vector3(velocity.x, 0, velocity.z).length() # also, if we're moving, we're not idle if move_direction.length() < 0.2: if velocity == Vector3.ZERO: _idle_time += delta + if _idle_time > idle_timeout: + _skin.set_idle() else: _last_movement_direction = move_direction _idle_time = 0.0 + _skin.set_grounded() # if camera is unlocked, rotate whole skin to face movement direction - # else, rotate to face camera pivot global Y direction var skin_target_angle := Vector3.BACK.signed_angle_to(_last_movement_direction, Vector3.UP) _skin.global_rotation.y = lerp_angle( _skin.global_rotation.y, skin_target_angle, rotation_speed * delta ) + + # lean into player momentum just a little bit + _skin.rotation.z = lerp_angle( + _skin.rotation.z, + clamp(_last_movement_direction.signed_angle_to(velocity, Vector3.UP) * movement_speed * 0.08, -PI/4, PI/ 4), + rotation_speed * delta * 0.25 + ) + + # let skin know how fast player is moving along the ground _skin.set_grounded_speed(movement_speed) # timescale tweaking for fun effect! - if movement_speed >= charge_speed * 0.75: + if _player_speed == charge_speed: _skin.set_timescale(2.0) - - # ignore objects when I'm going fast! - set_collision_mask_value(3, false) else: _skin.set_timescale(1.0) - set_collision_mask_value(3, true) func _process_player(delta: float) -> void: if is_on_floor(): - _skin.set_grounded() _process_player_on_floor(delta) + + _dust.emitting = velocity.length() > (0.75 * charge_speed) and is_on_floor() + _dust.amount_ratio = velocity.length() else: _skin.set_falling() velocity += get_gravity() * air_speed * delta # now actually move! - var movement_speed := velocity.length() + var velocity_length := velocity.length() move_and_slide() - + # handle collisions for i in get_slide_collision_count(): var c := get_slide_collision(i) if c.get_collider() is RigidBody3D: var col: RigidBody3D = c.get_collider() - col.apply_central_impulse(-c.get_normal() * push_force * movement_speed / col.mass) + col.apply_central_impulse(-c.get_normal() * velocity_length * push_force)