extends CharacterBody2D class_name MainPlayer enum MOVEMENT_STATUS { IDLE, WALKING, RUNNING, LAYING_STAY, LAYING_MOVING, CLIMBING_STAY, CLIMBING, } @export var player_movement_rect := Rect2(50, -500, 1400, 1000) @export var velocity_ratio := 1.0 @export var action_locked := false: set(val): action_locked = val _process_action_lock() @export var current_status: MOVEMENT_STATUS @export var facing_direction := Vector2(1.0, -1.0) @export var is_laying := false: set(val): is_laying = val # reset the facing direction wether the player is laying or not. _reset_face_direction() if is_laying: is_climbing = false @export var is_climbing := false: set(val): is_climbing = val # reset the facing direction wether the player is climbing or not. _reset_face_direction() if is_climbing: is_laying = false @export var running_locked := false @export var speed_walking := 90.0 @export var speed_runnig := 160.0 @export var speed_laying := 60.0 @export var speed_climbing := 60.0 #const JUMP_VELOCITY = -400.0 @export var footstep_base_speed := 60.0 @onready var footstep_timer = %FootstepTimer as Timer @onready var sprite = %AnimatedSprite2D as AnimatedSprite2D func _ready() -> void: # _reset_face_direction() footstep_timer.timeout.connect(_on_footstep_timer_timeout) footstep_timer.stop() func _on_footstep_timer_timeout(): # ground node is sibling of the player node. var ground_loader = SceneManager.get_ground_loader() if ground_loader: ground_loader.play_footstep_sound() func _reset_face_direction() -> void: facing_direction = Vector2(1, -1) func _process_action_lock() -> void: # reset status to idle or stay if action_locked: velocity = Vector2.ZERO if current_status == MOVEMENT_STATUS.WALKING or current_status == MOVEMENT_STATUS.RUNNING: current_status = MOVEMENT_STATUS.IDLE elif current_status == MOVEMENT_STATUS.LAYING_MOVING: current_status = MOVEMENT_STATUS.LAYING_STAY elif current_status == MOVEMENT_STATUS.CLIMBING: current_status = MOVEMENT_STATUS.CLIMBING_STAY _play_animation() # return whether the player status or facing direction has changed. func _check_status(direction) -> bool: var tmp_status = current_status var new_facing_direction := facing_direction if is_laying: if direction.x: new_facing_direction.x = direction.x tmp_status = MOVEMENT_STATUS.LAYING_MOVING else: tmp_status = MOVEMENT_STATUS.LAYING_STAY elif is_climbing: if direction.y: new_facing_direction.y = direction.y tmp_status = MOVEMENT_STATUS.CLIMBING else: tmp_status = MOVEMENT_STATUS.CLIMBING_STAY else: if direction.x: new_facing_direction.x = direction.x tmp_status = MOVEMENT_STATUS.WALKING if !running_locked and Input.is_action_pressed("run"): tmp_status = MOVEMENT_STATUS.RUNNING else: tmp_status = MOVEMENT_STATUS.IDLE if new_facing_direction != facing_direction or tmp_status != current_status: facing_direction = new_facing_direction current_status = tmp_status return true return false func set_facing_direction(direction: Vector2) -> void: facing_direction = direction # update status _check_status(direction) func _play_animation() -> void: match current_status: MOVEMENT_STATUS.IDLE: if facing_direction.x > 0.0: sprite.play(&"idle_r") else: sprite.play(&"idle_l") footstep_timer.stop() MOVEMENT_STATUS.WALKING: if facing_direction.x > 0.0: sprite.play(&"walking_r") else: sprite.play(&"walking_l") footstep_timer.wait_time = footstep_base_speed / speed_walking footstep_timer.start() MOVEMENT_STATUS.RUNNING: if facing_direction.x > 0.0: sprite.play(&"running_r") else: sprite.play(&"running_l") footstep_timer.wait_time = footstep_base_speed / speed_runnig footstep_timer.start() MOVEMENT_STATUS.LAYING_STAY: if facing_direction.x > 0.0: sprite.play(&"laying_stay_r") else: sprite.play(&"laying_stay_l") footstep_timer.stop() MOVEMENT_STATUS.LAYING_MOVING: if facing_direction.x > 0.0: sprite.play(&"laying_moving_r") else: sprite.play(&"laying_moving_l") footstep_timer.wait_time = footstep_base_speed / speed_laying footstep_timer.start() MOVEMENT_STATUS.CLIMBING_STAY: sprite.play(&"climbing_stay") footstep_timer.stop() MOVEMENT_STATUS.CLIMBING: if facing_direction.y > 0.0: sprite.play(&"climbing_down") else: sprite.play(&"climbing_up") footstep_timer.wait_time = footstep_base_speed / speed_climbing footstep_timer.start() func _get_speed(direction: Vector2) -> Vector2: match current_status: MOVEMENT_STATUS.WALKING: return Vector2(speed_walking * direction.x, 0.0) MOVEMENT_STATUS.RUNNING: return Vector2(speed_runnig * direction.x, 0.0) MOVEMENT_STATUS.LAYING_MOVING: return Vector2(speed_laying * direction.x, 0.0) MOVEMENT_STATUS.CLIMBING: return Vector2(0, speed_climbing * direction.y) return Vector2(0, 0) func _physics_process(_delta: float) -> void: if action_locked: velocity = Vector2.ZERO return # Add the gravity. #if not is_on_floor(): #velocity += get_gravity() * delta #if Input.is_action_just_pressed("jump") and is_on_floor(): #velocity.y = JUMP_VELOCITY var x_direction := Input.get_axis("left", "right") var y_direction := Input.get_axis("up", "down") var direction := Vector2(x_direction, y_direction) if _check_status(direction): _play_animation() var speed := _get_speed(direction) as Vector2 velocity.x = move_toward(velocity.x, speed.x, 300.0) * velocity_ratio velocity.y = move_toward(velocity.y, speed.y, 300.0) * velocity_ratio move_and_slide() position = position.clamp(player_movement_rect.position, player_movement_rect.end) _tweak_camera_marker() # drag the camera marker against the player movement # so there will be a better vision in front of the player. func _tweak_camera_marker(): var marker = get_node("./CameraFocusMarker") as Node2D if marker: marker.tweak_position(velocity, facing_direction) var note_mutex = Mutex.new() var note_pending_time = 0.0 var note_viewing = false func check_note(note_time): note_mutex.lock() note_pending_time += note_time if not note_viewing: note_viewing = true # velocity_ratio = 0.2 action_locked = true get_tree().create_timer(note_time).timeout.connect(_check_slow) note_mutex.unlock() func _check_slow(): note_mutex.lock() note_viewing = false action_locked = false # velocity_ratio = 1.0 note_mutex.unlock() if note_pending_time: note_pending_time = 0.0 check_note(note_pending_time)