extends KinematicBody2D class_name Player export var run_speed := 100.0 export var jump_power := 180.0 export var gravity: = 500.0 export var max_gravity:= 450.0 export var respawn_position:=Vector2.ZERO export var wall_slide_friction:=.2 export var wall_jump_speed_factor := Vector2(2.5 ,.85) export var dash_thrust = 500.0 export var max_wall_slide_gravity := 100.0 var LandingDust = load("res://src/Actors/LandingDust.tscn") var JumpDust = load("res://src/Actors/JumpDust.tscn") signal landed signal jumping signal died var _velocity: Vector2 = Vector2.ZERO var _landing_position:Vector2 = Vector2.ZERO var _in_air = false; var _is_wall_jumping := false var _alive := false; var _is_wall_sliding := false; var _is_dashing := false; var _can_dash := true; var _is_attaking := false; enum Direction{ RIGHT = 1, LEFT = -1 } export var abilities:= { "dash": false, "wall_jump": false, "attack": false } func _ready() -> void: $AnimationPlayer.play("fade_in") respawn_position = position func _physics_process(delta: float) -> void: if _alive: var is_jump_canceled: = Input.is_action_just_released("jump") and !_is_wall_jumping and _velocity.y < 0.0 var direction: = get_direction() var prev_wall_slide_state = _is_wall_sliding _is_wall_sliding = _velocity.y >=0 and is_on_wall() and _in_air _velocity = calculate_move_velocity(direction,is_jump_canceled, delta) if _is_wall_sliding and not prev_wall_slide_state: _velocity.y=0 _velocity = move_and_slide(_velocity, Vector2.UP) update_sprite(direction) if is_on_floor() and !_is_dashing: _can_dash = true; if is_on_floor() and _in_air and !_is_dashing: var dust = LandingDust.instance() dust.position = position get_parent().add_child(dust) _in_air = false _is_wall_jumping = false emit_signal("landed", position) if _is_wall_sliding: _is_wall_jumping = false func get_direction() -> Vector2: var right_strength = min(Input.get_action_strength("direction_right") , 1) var left_strength = min(Input.get_action_strength("direction_left"), 1) return Vector2( right_strength - left_strength if _in_air or not _is_attaking else 0, -1.0 if Input.is_action_just_pressed("jump") and (is_on_floor() or _is_wall_sliding) else 1.0 ) func calculate_move_velocity(direction:Vector2, is_jump_canceled:bool, delta:float)->Vector2: var output: = _velocity var current_gravity = gravity * wall_slide_friction if _is_wall_sliding else gravity output.x = lerp(_velocity.x, run_speed * direction.x, .09 if _in_air else .5) output.y += current_gravity * delta if direction.y == -1.0: # we are jumping _in_air = true if _is_wall_sliding: # wall jump var walljump__x_direction = -1 * direction.x _is_wall_jumping = true var desired = (run_speed * wall_jump_speed_factor.x * walljump__x_direction) output.x = desired output.y = jump_power * wall_jump_speed_factor.y * direction.y else: #jump output.y = jump_power * direction.y var dust = JumpDust.instance() dust.position = position; get_parent().add_child(dust) emit_signal("jumping", position) if not _is_dashing: if is_jump_canceled: output.y = 0 if output.y < max_gravity * -1: output.y = max_gravity if output.y > 0 and !is_on_floor(): _in_air = true; if _is_dashing: return _velocity if _is_wall_sliding and output.y > max_wall_slide_gravity: output.y = max_wall_slide_gravity var dash_velocity := Vector2( $Sprite.scale.x * dash_thrust, 0 ) if Input.is_action_just_pressed("dash") and _can_dash: _can_dash = false _is_dashing = true # turn off gravity while dashing # Wall dash first if _is_wall_sliding: dash_velocity.x = $Sprite.scale.x * dash_thrust * -1 if dash_velocity.x < 0 : $DashParticlesLeft.emitting = true; else: $DashParticlesRight.emitting = true output = dash_velocity $DashTimeout.start() return output; func _respawn(): position = respawn_position _velocity = Vector2.ZERO $AnimationPlayer.play("fade_in") func _revive(): _alive = true func update_sprite(_direction:Vector2) -> void: var air_animation = "jump" if _velocity.y <= 0 else "fall" if _is_attaking: return var attack = Input.is_action_just_pressed("attack") and abilities.attack if _velocity.x > .5 and not _is_wall_sliding: $Sprite.scale = Vector2(1,1) $AnimationPlayer.play("run" if is_on_floor() else air_animation) elif _velocity.x < -.5 and not _is_wall_sliding: $Sprite.scale = Vector2(-1,1) $AnimationPlayer.play("run" if is_on_floor() else air_animation) else: if not _in_air: $AnimationPlayer.play("idle") if _is_wall_sliding: $AnimationPlayer.play("wall_slide") return if attack: _is_attaking = true AudioManager.play_sfx(AudioManager.Sfx.PLAYER_ATTACK) var attack_animation = "attack_right" if $Sprite.scale.x > 0 else "attack_left" $AnimationPlayer.play(attack_animation) $AnimationPlayer.playback_speed = 2.5 $AnimationPlayer.seek(0) yield($AnimationPlayer, "animation_finished") $AnimationPlayer.playback_speed = 1 _is_attaking = false return if _in_air: $AnimationPlayer.play(air_animation) return if _is_dashing: $AnimationPlayer.play("jump") return func _on_die_animation_done(): emit_signal("died") _respawn() func die(): _alive = false $AnimationPlayer.play("die") func setAbility(ability:String, enabled:bool=false): if ability == 'dash': abilities.dash = enabled elif ability == 'wall_jump': abilities.wall_jump = enabled elif ability == 'attack': abilities.attack = enabled else: pass func _on_DashTimeout_timeout() -> void: $DashParticlesLeft.emitting = false $DashParticlesRight.emitting = false _velocity.x = run_speed * _velocity.normalized().x; _is_dashing = false pass # Replace with function body. func _on_SordRange_body_entered(body: Node) -> void: if body.is_in_group("Enemies"): body.take_damage($Sprite.scale.x) pass # Replace with function body.