extends KinematicBody2D ##CLEAN UP CODE LATER ##Children onready var sprite = $Sprite onready var climb_ray = $ClimbRay onready var anims = $AnimationPlayer onready var sword_sprite = $SwordSprite onready var sword_hitbox = $SwordArea #Map onready var map = get_owner() ##States enum State {IDLE,WALK,JUMP,FALL,STUNNED,CLIMB,SWORD,SHOOT} var current_state = State.IDLE var axis = Vector2.ZERO ##Physics var velocity = Vector2.ZERO var walk_speed = 50 var gravity = 12 var jump_pressure = 0 var jump_force = 150 var current_ladder = null var can_doublejump = true var doublejump_force = 120 var arrowpos = Vector2(5,3) #Preload var pre_arrow = preload("res://objects/player/arrow_projectile.tscn") func _physics_process(delta): axis = Vector2(Input.get_axis("ui_left","ui_right"),Input.get_axis("ui_up","ui_down")) #Check ladder check_ladder() match current_state: State.IDLE: _process_idle() continue State.WALK: _process_walk() continue State.IDLE, State.WALK: _process_idle_walk() State.JUMP: _process_jump() continue State.FALL: _process_fall() continue State.CLIMB: _process_climb() continue State.SWORD: _process_sword() continue State.SHOOT: _process_shoot() #Gravity if current_state != State.CLIMB: velocity.y += gravity #Apply velocity move_and_slide(velocity,Vector2.UP) #Debug if Input.is_action_pressed("debug_move_player"): position = get_viewport().get_mouse_position() print(get_viewport().get_mouse_position()) func _process_idle(): if anims.get_current_animation() != "idle": anims.play("idle") #Stop velocity.x = 0 #Goto Walk if axis.x != 0: current_state = State.WALK func _process_walk(): if anims.get_current_animation() != "walk": anims.play("walk") #Move move(walk_speed,0,true) #Goto Idle if axis.x == 0: current_state = State.IDLE #Push Blocks for i in get_slide_count(): var collision = get_slide_collision(i) if collision.get_collider().is_in_group("pushable"): print(collision.get_collider()) collision.get_collider().push(collision.normal) func _process_idle_walk(): velocity.y = 0 can_doublejump = true #Goto Fall if !is_on_floor(): current_state = State.FALL #Goto Jump check_jump() #Goto Sword if Input.is_action_just_pressed("sword"): Game.play_sound(Game.a_sword,Game.ac_jump) current_state = State.SWORD return #Goto Shoot check_shoot() func _process_jump(): jump_pressure += 1 move(walk_speed,0,true) check_double_jump() #Pressure sensitive jump if jump_pressure == 15 or Input.is_action_just_released("jump"): velocity.y = -jump_force / 4 #velocity.y = 0 current_state = State.FALL #Goto Shoot check_shoot() func _process_fall(): if anims.get_current_animation() != "doublejump": anims.play("jump") check_double_jump() #anims.play("jump") move(walk_speed,0,true) #Return to idle if is_on_floor(): current_state = State.IDLE return #Goto Shoot check_shoot() func _process_climb(): can_doublejump = true #Graphics anims.play("climb") anims.set_speed_scale(abs(axis.y)) #Climb position.y += axis.y * 0.65 #Sound if axis.y == -1: if Game.ac_climb.get_stream() != Game.a_climb_up: Game.play_sound(Game.a_climb_up,Game.ac_climb) if axis.y == 1: if Game.ac_climb.get_stream() != Game.a_climb_down: Game.play_sound(Game.a_climb_down,Game.ac_climb) if axis.y == 0: Game.ac_climb.set_stream(null) #Manual Jump,, only works when holding neutral or away from ladder if axis.x != sprite.scale.x: check_jump() #Auto Jump if climb_ray.get_collider() == null: velocity.y = -jump_force Game.ac_climb.set_stream(null) Game.play_sound(Game.a_jump,Game.ac_jump) current_state = State.FALL return func _process_sword(): anims.play("stab") #Stop velocity.x = 0 sword_sprite.scale.x = sprite.scale.x #Move hitbox with flip sword_hitbox.position.x = sprite.scale.x * 10 #Return to idle after animationplayer end anim signal func _process_shoot(): #Stop velocity.x = 0 if anims.get_current_animation() == "shoot air": #Cancel air shoot animation when grounded if is_on_floor(): current_state = State.IDLE return move(walk_speed,0,true) func spawn_arrow(): Game.play_sound(Game.a_shoot,Game.ac_jump) Game.instance_node(pre_arrow,global_position.x+(arrowpos.x*sprite.scale.x),global_position.y+arrowpos.y,map) func check_jump(): if Input.is_action_just_pressed("jump"): #Detach ladder if current_state == State.CLIMB: Game.ac_climb.set_stream(null) # stop climb sound position.x -= sprite.scale.x * 5 anims.set_speed_scale(1) # Jump velocity.y = 0 jump_pressure = 0 current_state = State.JUMP Game.play_sound(Game.a_jump,Game.ac_jump) anims.play("jump") velocity.y = -jump_force move(walk_speed,0,true) func check_double_jump(): if Input.is_action_just_pressed("jump") && can_doublejump: Game.play_sound(Game.a_doublejump,Game.ac_jump) can_doublejump = false velocity.y = -doublejump_force anims.play("doublejump") func check_shoot(): #Only Shoot if have arrows and there are no arrows onscreen if Input.is_action_just_pressed("shoot") && Game.arrows > 0 && get_tree().get_nodes_in_group("arrow").size() == 0: current_state = State.SHOOT if is_on_floor(): anims.play("shoot grounded") else: anims.play("shoot air") #Shoot immediately in air func move(hsp,vsp,flip:bool): velocity.x = hsp * axis.x #Flip if flip: if sign(axis.x) != 0: sprite.scale.x = axis.x func check_ladder(): if climb_ray.get_collider() != null: current_ladder = climb_ray.get_collider().get_parent() #Stop the velocity velocity = Vector2.ZERO #Snap to closest side if position.x < current_ladder.middle: position.x = current_ladder.left_snap.global_position.x sprite.scale.x = 1 else: position.x = current_ladder.right_snap.global_position.x sprite.scale.x = -1 #Start Climbing current_state = State.CLIMB #Move the raycast climb_ray.position.x = 4 * sprite.scale.x func die(): get_tree().reload_current_scene() func _on_AnimationPlayer_animation_finished(anim_name): #Return to idle after slash if anim_name == "stab": current_state = State.IDLE return #Return to idle after grounded shoot if anim_name == "shoot grounded": current_state = State.IDLE return #Return to fall or idle after air shoot if anim_name == "shoot air": if is_on_floor(): current_state = State.IDLE return else: current_state = State.FALL return