tenchu/Godot/Code/Character.gd

195 lines
4.0 KiB
GDScript

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 {
}