Add DodgeState

This commit is contained in:
TheThomaas 2026-09-27 10:31:36 +02:00
parent 082f834d61
commit 042840309d
9 changed files with 117 additions and 1 deletions

View file

@ -12,6 +12,7 @@ class_name InputManagementComponent
@export var move_right_action : StringName = "player_move_right"
@export var run_action : StringName = "player_run"
@export var jump_action : StringName = "player_jump"
@export var dodge_action : StringName = "player_dodge"
@export_subgroup("Camera variables")
@export var aim_cam_action : StringName = "player_aim_camera"
@export var cam_zoom_in_action : StringName = "player_zoom_camera_in"
@ -36,6 +37,7 @@ func attribute_keybinds() -> void:
play_char_ref.move_right_action = move_right_action
play_char_ref.run_action = run_action
play_char_ref.jump_action = jump_action
play_char_ref.dodge_action = dodge_action
play_char_ref.aim_cam_action = aim_cam_action
cam_holder_ref.aim_cam_action = aim_cam_action

View file

@ -9,6 +9,7 @@
[ext_resource type="Script" uid="uid://dr5p8ygj25w6x" path="res://game/player/StateMachine/JumpState.gd" id="6_lwgph"]
[ext_resource type="Script" uid="uid://dn5idrvu68k83" path="res://game/player/StateMachine/AimState.gd" id="7_kxr4l"]
[ext_resource type="Script" uid="uid://dpcfffs3vt5co" path="res://game/player/StateMachine/RunState.gd" id="8_j4mf1"]
[ext_resource type="Script" uid="uid://bwojkp7yrwswt" path="res://game/player/StateMachine/DodgeState.gd" id="9_6abew"]
[sub_resource type="Curve" id="Curve_kxr4l"]
_limits = [0.0, 10.0, 0.0, 1.0]
@ -85,5 +86,8 @@ script = ExtResource("7_kxr4l")
[node name="RunState" type="Node" parent="StateMachine" unique_id=1345421775]
script = ExtResource("8_j4mf1")
[node name="DodgeState" type="Node" parent="StateMachine" unique_id=232179400]
script = ExtResource("9_6abew")
[node name="InputManagementComponent" type="Node" parent="." unique_id=1981951371]
script = ExtResource("2_r5dqo")

View file

@ -23,6 +23,7 @@ var play_char : CharacterBody3D
@export var aim_move_accel : float = 8.0
var auto_lock_blocked : bool = false #true apres un deverrouillage manuel, tant que la cible est encore au centre
var dodging_from_aim : bool = false #true quand on quitte Aim pour rouler, pour ne pas relacher la cible verrouillee
func enter(play_char_ref : CharacterBody3D) -> void:
play_char = play_char_ref
@ -34,6 +35,10 @@ func verifications() -> void:
play_char.cam_holder.cam_aimed = true
func exit() -> void:
if dodging_from_aim:
#on roule en visant : la camera et la cible verrouillee restent actives pendant la roulade
dodging_from_aim = false
return
release_target()
if play_char: play_char.cam_holder.cam_aimed = false
@ -51,6 +56,11 @@ func applies() -> bool:
return false
func input_management() -> bool:
if Input.is_action_just_pressed(play_char.dodge_action) and play_char.dodge_cooldown <= 0.0:
dodging_from_aim = true
transitioned.emit(self, "DodgeState")
return true
if !Input.is_action_pressed(aim_action):
transitioned.emit(self, play_char.walk_or_run if play_char.move_dir else "IdleState")
return true

View file

@ -0,0 +1,76 @@
extends State
class_name DodgeState
var state_name : String = "Dodge"
var play_char : CharacterBody3D
@export var dodge_speed_curve : Curve #optionnel : controle le "falloff" de vitesse pendant la roulade (1.0 = pleine vitesse, 0.0 = arret). Laisser vide pour une vitesse constante.
var dodge_dir : Vector2 = Vector2.ZERO
var dodge_timer : float = 0.0
var dodge_duration_ref : float = 0.0
func enter(play_char_ref : CharacterBody3D) -> void:
play_char = play_char_ref
verifications()
func verifications() -> void:
play_char.floor_snap_length = 1.0
play_char.is_dodging = true
play_char.dodge_cooldown = play_char.dodge_cooldown_ref
#roule dans la direction actuelle de l'input, ou dans la derniere direction connue si aucune touche n'est tenue (comportement Arceus)
dodge_dir = play_char.move_dir if play_char.move_dir != Vector2.ZERO else play_char.last_input_dir
if dodge_dir == Vector2.ZERO: dodge_dir = Vector2.DOWN #direction par defaut si le perso n'a encore jamais bouge
dodge_dir = dodge_dir.normalized()
dodge_timer = play_char.dodge_duration
dodge_duration_ref = play_char.dodge_duration
#oriente immediatement le modele dans la direction de la roulade, verrouillee pour toute sa duree
play_char.visual_root.rotation.y = -dodge_dir.orthogonal().angle()
func exit() -> void:
play_char.is_dodging = false
func physics_update(delta : float) -> void:
applies()
play_char.gravity_apply(delta)
move(delta)
dodge_timer -= delta
if dodge_timer <= 0.0:
end_dodge()
func applies() -> void:
#si le perso quitte le sol en roulant (ex: roulade vers un bord), on bascule vers InairState comme les autres etats au sol
if !play_char.is_on_floor() and !play_char.is_on_wall():
if play_char.velocity.y < 0.0:
transitioned.emit(self, "InairState")
func move(_delta : float) -> void:
if !play_char.is_on_floor(): return
#falloff de vitesse : pleine vitesse par defaut, ou modele par dodge_speed_curve si assignee
var ratio : float = 1.0
if dodge_speed_curve:
ratio = dodge_speed_curve.sample(1.0 - (dodge_timer / dodge_duration_ref))
play_char.velocity.x = dodge_dir.x * play_char.dodge_speed * ratio
play_char.velocity.z = dodge_dir.y * play_char.dodge_speed * ratio
func end_dodge() -> void:
#a la fin de la roulade, retour a l'etat approprie
if !play_char.is_on_floor():
transitioned.emit(self, "InairState")
elif Input.is_action_pressed(play_char.aim_cam_action):
transitioned.emit(self, "AimState") #le joueur a garde la visee enfoncee pendant la roulade
elif play_char.move_dir:
transitioned.emit(self, play_char.walk_or_run)
else:
transitioned.emit(self, "IdleState")

View file

@ -0,0 +1 @@
uid://bwojkp7yrwswt

View file

@ -44,6 +44,9 @@ func applies() -> void:
func input_management() -> void:
#manage the state transitions depending on the actions inputs
if Input.is_action_just_pressed(play_char.dodge_action) and play_char.dodge_cooldown <= 0.0:
transitioned.emit(self, "DodgeState")
if Input.is_action_pressed(play_char.jump_action) if play_char.auto_jump else Input.is_action_just_pressed(play_char.jump_action):
transitioned.emit(self, "JumpState")

View file

@ -13,6 +13,7 @@ var last_frame_position : Vector3
var last_frame_velocity : Vector3
var was_on_floor : bool = false
var walk_or_run : String = "WalkState" #keep in memory if play char was walking or running before being in the air
var is_dodging : bool = false #true while DodgeState is active ; hook this up to a hurtbox/i-frame check later
@export_group("Walk variables")
@export var walk_speed : float = 5.0
@ -25,6 +26,12 @@ var walk_or_run : String = "WalkState" #keep in memory if play char was walking
@export var run_deccel : float = 6.5
@export var continious_run : bool = false #if true, doesn't need to keep run button on to run
@export_group("Dodge variables")
@export var dodge_speed : float = 10.0
@export var dodge_duration : float = 0.4
@export var dodge_cooldown : float = 0.6
var dodge_cooldown_ref : float
@export_group("Jump variables")
@export var jump_height : float = 3.0
@export var jump_time_to_peak : float = 0.35
@ -94,15 +101,17 @@ func _ready():
jump_cooldown_ref = jump_cooldown
nb_jumps_in_air_allowed_ref = nb_jumps_in_air_allowed
coyote_jump_cooldown_ref = coyote_jump_cooldown
dodge_cooldown_ref = dodge_cooldown
#connect_footstep_audio_effect()
func _process(delta: float):
modify_model_orientation(delta)
func _physics_process(_delta : float):
func _physics_process(delta : float):
update_run_toggle()
modify_physics_properties()
tick_dodge_cooldown(delta)
move_and_slide()
@ -137,6 +146,11 @@ func modify_physics_properties():
last_frame_position = position #get play char position every frame
last_frame_velocity = velocity #get play char velocity every frame
was_on_floor = !is_on_floor() #get if play char is on floor or not
if move_dir != Vector2.ZERO: last_input_dir = move_dir #memorize the last non-zero input direction, used as a dodge fallback
func tick_dodge_cooldown(delta : float) -> void:
if dodge_cooldown > 0.0:
dodge_cooldown -= delta
func gravity_apply(delta : float):
#if play char goes up, apply jump gravity

View file

@ -46,6 +46,9 @@ func applies() -> void:
transitioned.emit(self, "JumpState")
func input_management() -> void:
if Input.is_action_just_pressed(play_char.dodge_action) and play_char.dodge_cooldown <= 0.0:
transitioned.emit(self, "DodgeState")
if Input.is_action_pressed(play_char.jump_action) if play_char.auto_jump else Input.is_action_just_pressed(play_char.jump_action):
transitioned.emit(self, "JumpState")

View file

@ -46,6 +46,9 @@ func applies() -> void:
transitioned.emit(self, "JumpState")
func input_management() -> void:
if Input.is_action_just_pressed(play_char.dodge_action) and play_char.dodge_cooldown <= 0.0:
transitioned.emit(self, "DodgeState")
if Input.is_action_pressed(play_char.jump_action) if play_char.auto_jump else Input.is_action_just_pressed(play_char.jump_action) :
transitioned.emit(self, "JumpState")