extends CharacterBody2D var gravity = 900 var gravity_mid = 500 var gravity_fall = 1300 const SPEED = 200.0 const JUMP_VELOCITY = -300.0 const roll_speed = 300 var roll_cooldown_time = 0.5 var colshape_stand = 30 @onready var sprite = $Sprites var land_time = 0 var roll_cooldown = 0 var roll_time = 0 var roll_dir = 1 var side = 1 var state = State.Idle var double_jump = false enum State { Idle, Run, Walk, Jump, AirSpin, Land, Attack, Roll, OnWall, } enum RState { Grounded, Aerial, Combat, Climbing } # A state machine might be needed here because this is getting really messy? # There are 4 major states; grounded, combat, aerial, climbing var rstate = RState.Aerial func grounded(delta): if land_time >= 0: land_time -= delta if roll_cooldown >= 0: roll_cooldown -= delta if roll_time >= 0: roll_time -= delta elif state == State.Roll: $CollisionShape2D.shape.size.y = colshape_stand $CollisionShape2D.position.y = colshape_stand / -2 roll_cooldown = roll_cooldown_time # state = State.Idle if Input.is_action_just_pressed("attack"): rstate = RState.Combat return if Input.is_action_just_pressed("roll"): if is_on_floor() and roll_time <= 0 and roll_cooldown <= 0: # state = State.Roll roll_time = 0.55 roll_dir = -1 if sprite.flip_h else 1 $CollisionShape2D.shape.size.y = colshape_stand / 2 $CollisionShape2D.position.y = colshape_stand / -4 sprite.play("GroundRoll") return if Input.is_action_just_pressed("ui_accept") and state != State.Roll: velocity.y = JUMP_VELOCITY sprite.play("Jump") rstate = RState.Aerial sprite.pause() sprite.set_frame_and_progress(0, 0) return # We ran off of a ledge if not is_on_floor(): rstate = RState.Aerial return if state == State.Roll: velocity.x = roll_dir * roll_speed else: var speed = SPEED if Input.is_key_pressed(KEY_SHIFT): speed /= 3 var direction = Input.get_axis("left", "right") if direction: velocity.x = direction * speed else: # Decelerate velocity.x = move_toward(velocity.x, 0, 25) if direction != 0: sprite.flip_h = direction == -1 if land_time <= 0: if velocity.x != 0: if Input.is_key_pressed(KEY_SHIFT): sprite.play("Walk") else: sprite.play("Run") else: sprite.play("Idle") func aerial(delta): if is_on_floor(): # Transition to grounded double_jump = false rstate = RState.Grounded sprite.play("Land") land_time = 0.16 return if is_on_wall(): rstate = RState.Climbing return # if Input.is_action_just_pressed("ui_accept") and state != State.AirSpin: if Input.is_action_just_pressed("ui_accept") and not double_jump: sprite.play("AirSpin") double_jump = true # state = State.AirSpin var boost = 0 if velocity.y > 0 else velocity.y / 3 velocity.y = JUMP_VELOCITY / 1.4 + boost if velocity.y > 50: velocity.y += gravity_fall * delta elif velocity.y < -50: velocity.y += gravity * delta else: velocity.y += gravity_mid * delta var direction = Input.get_axis("left", "right") if direction: velocity.x = direction * SPEED * 0.9 elif double_jump: # Decelerate velocity.x = move_toward(velocity.x, 0, 3) else: velocity.x = move_toward(velocity.x, 0, 9) if direction != 0: sprite.flip_h = direction == -1 if not double_jump: if velocity.y > 50: sprite.set_frame_and_progress(2,0) elif velocity.y > -150: sprite.set_frame_and_progress(1, 0) func combat(delta): # state = State.Attack velocity = Vector2.ZERO sprite.play("Attack1") await (sprite as AnimatedSprite2D).animation_finished # state = State.Idle rstate = RState.Grounded func climbing(delta): if Input.is_action_just_pressed("ui_accept"): rstate = RState.Aerial velocity.x = -150 velocity.y = -350 return velocity.x = 0 velocity.y = 0 func _physics_process(delta): match rstate: RState.Grounded: grounded(delta) RState.Aerial: aerial(delta) RState.Combat: combat(delta) RState.Climbing: climbing(delta) # if (state == State.Jump or state == State.AirSpin) and is_on_wall(): # state = State.OnWall # return move_and_slide() # Maybe later enum JumpState { }