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 anim = new_anim $anims.play(anim) 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