204 lines
5.3 KiB
GDScript
204 lines
5.3 KiB
GDScript
extends CharacterBody2D
|
|
|
|
class_name Player
|
|
|
|
"""
|
|
This implements a very rudimentary state machine. There are better implementations
|
|
in the AssetLib if you want to make something more complex. Also it shares code with Enemy.gd
|
|
and probably both should extend some parent script
|
|
"""
|
|
|
|
@export var WALK_SPEED: int = 70 # pixels per second
|
|
@export var ROLL_SPEED: int = 1000 # pixels per second
|
|
@export var hitpoints: int = 3
|
|
|
|
var linear_vel = Vector2()
|
|
var roll_direction = Vector2.DOWN
|
|
|
|
signal health_changed(current_hp)
|
|
|
|
var despawn_fx = preload("res://scenes/misc/DespawnFX.tscn")
|
|
|
|
var anim = ""
|
|
var new_anim = ""
|
|
|
|
const N = Vector2.UP
|
|
const NE = Vector2(cos(1*PI/4),sin(1*PI/4))
|
|
const E = Vector2.RIGHT
|
|
const SE = Vector2(cos(7*PI/4),sin(7*PI/4))
|
|
const S = Vector2.DOWN
|
|
const SW = Vector2(cos(5*PI/4),sin(5*PI/4))
|
|
const W = Vector2.LEFT
|
|
const NW = Vector2(cos(3*PI/4),sin(3*PI/4))
|
|
|
|
|
|
|
|
enum { STATE_BLOCKED, STATE_IDLE, STATE_WALKING, STATE_ATTACK, STATE_ROLL, STATE_DIE, STATE_HURT }
|
|
|
|
|
|
@export var facing = "S" # (String, "up", "down", "left", "right")
|
|
var state = STATE_IDLE
|
|
var direction = S
|
|
|
|
# Move the player to the corresponding spawnpoint, if any and connect to the dialog system
|
|
func _ready():
|
|
var spawnpoints = get_tree().get_nodes_in_group("spawnpoints")
|
|
for spawnpoint in spawnpoints:
|
|
if spawnpoint.name == Globals.spawnpoint:
|
|
global_position = spawnpoint.global_position
|
|
break
|
|
if not (
|
|
Dialogs.dialog_started.connect(_on_dialog_started) == OK and
|
|
Dialogs.dialog_ended.connect(_on_dialog_ended) == OK ):
|
|
printerr("Error connecting to dialog system")
|
|
pass
|
|
|
|
|
|
func _physics_process(_delta):
|
|
|
|
## PROCESS STATES
|
|
match state:
|
|
STATE_BLOCKED:
|
|
# new_anim = "idle_" + facing
|
|
$anims.stop()
|
|
pass
|
|
STATE_IDLE:
|
|
if (
|
|
Input.is_action_pressed("move_down") or
|
|
Input.is_action_pressed("move_left") or
|
|
Input.is_action_pressed("move_right") or
|
|
Input.is_action_pressed("move_up")
|
|
):
|
|
state = STATE_WALKING
|
|
if Input.is_action_just_pressed("attack"):
|
|
state = STATE_ATTACK
|
|
# if Input.is_action_just_pressed("roll"):
|
|
# state = STATE_ROLL
|
|
# roll_direction = Vector2(
|
|
# - int( Input.is_action_pressed("move_left") ) + int( Input.is_action_pressed("move_right") ),
|
|
# -int( Input.is_action_pressed("move_up") ) + int( Input.is_action_pressed("move_down") )
|
|
# ).normalized()
|
|
# _update_facing()
|
|
|
|
# new_anim = "idle_" + facing
|
|
$anims.stop()
|
|
pass
|
|
STATE_WALKING:
|
|
if Input.is_action_just_pressed("attack"):
|
|
state = STATE_ATTACK
|
|
if Input.is_action_just_pressed("roll"):
|
|
state = STATE_ROLL
|
|
|
|
linear_vel = velocity
|
|
|
|
var target_speed = Vector2(0,0)
|
|
|
|
if Input.is_action_pressed("move_down"):
|
|
target_speed += Vector2.DOWN
|
|
if Input.is_action_pressed("move_left"):
|
|
target_speed += Vector2.LEFT
|
|
if Input.is_action_pressed("move_right"):
|
|
target_speed += Vector2.RIGHT
|
|
if Input.is_action_pressed("move_up"):
|
|
target_speed += Vector2.UP
|
|
|
|
|
|
target_speed = target_speed.normalized() * WALK_SPEED
|
|
target_speed.y *= 0.50 # compensa visione isometrica
|
|
#linear_vel = linear_vel.linear_interpolate(target_speed, 0.9)
|
|
linear_vel = target_speed
|
|
set_velocity(linear_vel)
|
|
roll_direction = linear_vel.normalized()
|
|
move_and_slide()
|
|
|
|
_update_facing()
|
|
|
|
if linear_vel.length() > 5:
|
|
new_anim = "walk_" + facing
|
|
$anims.play()
|
|
else:
|
|
goto_idle()
|
|
pass
|
|
STATE_ATTACK:
|
|
new_anim = "walk_" + facing # was splash_
|
|
pass
|
|
STATE_ROLL:
|
|
if roll_direction == Vector2.ZERO:
|
|
state = STATE_IDLE
|
|
else:
|
|
set_velocity(linear_vel)
|
|
move_and_slide()
|
|
linear_vel = velocity
|
|
var target_speed = Vector2()
|
|
target_speed = roll_direction
|
|
target_speed *= ROLL_SPEED
|
|
#linear_vel = linear_vel.linear_interpolate(target_speed, 0.9)
|
|
linear_vel = target_speed
|
|
new_anim = "roll"
|
|
STATE_DIE:
|
|
new_anim = "die"
|
|
STATE_HURT:
|
|
new_anim = "hurt"
|
|
|
|
## UPDATE ANIMATION
|
|
if new_anim != anim:
|
|
anim = new_anim
|
|
$anims.play(anim)
|
|
pass
|
|
|
|
|
|
func _on_dialog_started():
|
|
state = STATE_BLOCKED
|
|
|
|
func _on_dialog_ended():
|
|
state = STATE_IDLE
|
|
|
|
|
|
## HELPER FUNCS
|
|
func goto_idle():
|
|
linear_vel = Vector2.ZERO
|
|
# new_anim = "idle_" + facing
|
|
state = STATE_IDLE
|
|
|
|
|
|
func _update_facing():
|
|
if Input.is_action_pressed("move_left"):
|
|
facing = "W"
|
|
if Input.is_action_pressed("move_right"):
|
|
facing = "E"
|
|
if Input.is_action_pressed("move_up"):
|
|
facing = "N"
|
|
if Input.is_action_pressed("move_left"):
|
|
facing = "NW"
|
|
if Input.is_action_pressed("move_right"):
|
|
facing = "NE"
|
|
if Input.is_action_pressed("move_down"):
|
|
facing = "S"
|
|
if Input.is_action_pressed("move_left"):
|
|
facing = "SW"
|
|
if Input.is_action_pressed("move_right"):
|
|
facing = "SE"
|
|
|
|
|
|
func despawn():
|
|
var despawn_particles = despawn_fx.instantiate()
|
|
get_parent().add_child(despawn_particles)
|
|
despawn_particles.global_position = global_position
|
|
hide()
|
|
await get_tree().create_timer(5.0).timeout
|
|
get_tree().reload_current_scene()
|
|
pass
|
|
|
|
|
|
func _on_hurtbox_area_entered(area):
|
|
if state != STATE_DIE and area.is_in_group("enemy_weapons"):
|
|
hitpoints -= 1
|
|
emit_signal("health_changed", hitpoints)
|
|
var pushback_direction = (global_position - area.global_position).normalized()
|
|
set_velocity(pushback_direction * 5000)
|
|
move_and_slide()
|
|
state = STATE_HURT
|
|
if hitpoints <= 0:
|
|
state = STATE_DIE
|
|
pass
|