Update throwing mechanics
This commit is contained in:
parent
0398ac3345
commit
1a1ecf602f
|
|
@ -43,7 +43,10 @@ func enter(play_char_ref : CharacterBody3D) -> void:
|
||||||
play_char = play_char_ref
|
play_char = play_char_ref
|
||||||
auto_lock_blocked = false
|
auto_lock_blocked = false
|
||||||
#curr_state_name n'est pas encore mis a jour a ce stade : il reflete encore l'etat qu'on est en train de quitter
|
#curr_state_name n'est pas encore mis a jour a ce stade : il reflete encore l'etat qu'on est en train de quitter
|
||||||
came_from_crouch = play_char.state_machine.curr_state_name == "Crouch"
|
#si on revient de ThrowState, came_from_crouch a deja ete transmis par ThrowState : on ne l'ecrase pas
|
||||||
|
var previous : String = play_char.state_machine.curr_state_name
|
||||||
|
if previous != "Throw" and previous != "Dodge":
|
||||||
|
came_from_crouch = previous == "Crouch"
|
||||||
verifications()
|
verifications()
|
||||||
|
|
||||||
func verifications() -> void:
|
func verifications() -> void:
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@ extends Node
|
||||||
class_name StateMachine
|
class_name StateMachine
|
||||||
|
|
||||||
@export var initial_state : State
|
@export var initial_state : State
|
||||||
|
@export var throw_action : StringName = &"player_throw"
|
||||||
|
|
||||||
|
const THROW_ENTRY_STATES : Array[String] = ["Idle", "Walk", "Run", "Crouch"] #etats depuis lesquels RT lance sans viser
|
||||||
|
|
||||||
var curr_state : State
|
var curr_state : State
|
||||||
var curr_state_name : String
|
var curr_state_name : String
|
||||||
|
|
@ -27,8 +30,29 @@ func _ready() -> void:
|
||||||
func _process(delta : float) -> void:
|
func _process(delta : float) -> void:
|
||||||
if curr_state: curr_state.update(delta)
|
if curr_state: curr_state.update(delta)
|
||||||
|
|
||||||
|
|
||||||
func _physics_process(delta: float) -> void:
|
func _physics_process(delta: float) -> void:
|
||||||
if curr_state: curr_state.physics_update(delta)
|
if curr_state:
|
||||||
|
if try_start_throw(): return
|
||||||
|
curr_state.physics_update(delta)
|
||||||
|
|
||||||
|
func try_start_throw() -> bool:
|
||||||
|
if !(curr_state_name in THROW_ENTRY_STATES): return false
|
||||||
|
if !Input.is_action_just_pressed(throw_action): return false
|
||||||
|
if !char_ref.is_on_floor(): return false
|
||||||
|
|
||||||
|
var selected : PokemonInstance = GameData.get_selected_pokemon()
|
||||||
|
if selected == null: return false
|
||||||
|
|
||||||
|
#pokemon deja dehors : l'appui le rappelle au lieu de lancer
|
||||||
|
var already_out : SentPokemon = SentPokemon.find_for(get_tree(), selected)
|
||||||
|
if already_out:
|
||||||
|
already_out.recall()
|
||||||
|
return false
|
||||||
|
|
||||||
|
if !states.has("throwstate"): return false
|
||||||
|
on_state_child_transition(curr_state, "ThrowState")
|
||||||
|
return true
|
||||||
|
|
||||||
func on_state_child_transition(state : State, new_state_name : String) -> void:
|
func on_state_child_transition(state : State, new_state_name : String) -> void:
|
||||||
#manage the transition from one state to another
|
#manage the transition from one state to another
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,15 @@ var state_name : String = "Throw"
|
||||||
var play_char : CharacterBody3D
|
var play_char : CharacterBody3D
|
||||||
|
|
||||||
@export var aim_action : StringName = &"player_aim_camera"
|
@export var aim_action : StringName = &"player_aim_camera"
|
||||||
|
@export var throw_action : StringName = &"player_throw" #RT / clic gauche : maintenir pour charger, relacher pour lancer
|
||||||
|
@export var cancel_action : StringName = &"player_throw_cancel" #B / clic droit (cree automatiquement s'il n'existe pas)
|
||||||
|
|
||||||
|
@export_group("Charge")
|
||||||
|
@export var charge_move_speed : float = 3.0 #vitesse de deplacement pendant que RT est maintenue
|
||||||
|
@export var charge_move_accel : float = 8.0
|
||||||
|
|
||||||
@export_group("Timing")
|
@export_group("Timing")
|
||||||
@export var windup_time : float = 0.25 #delai avant que la balle parte (a caler sur l'animation)
|
@export var windup_time : float = 0.25 #delai entre le relachement et le depart de la balle (a caler sur l'animation)
|
||||||
@export var recovery_time : float = 0.35 #temps de recuperation apres le lancer
|
@export var recovery_time : float = 0.35 #temps de recuperation apres le lancer
|
||||||
|
|
||||||
@export_group("Ball")
|
@export_group("Ball")
|
||||||
|
|
@ -26,21 +32,56 @@ var play_char : CharacterBody3D
|
||||||
@export_flags_3d_physics var ground_mask : int = 1
|
@export_flags_3d_physics var ground_mask : int = 1
|
||||||
|
|
||||||
var _elapsed : float = 0.0
|
var _elapsed : float = 0.0
|
||||||
|
var _released : bool = false #true des que RT est relachee (phase windup/recovery)
|
||||||
var _thrown : bool = false
|
var _thrown : bool = false
|
||||||
var _keep_aim : bool = false #true quand on retourne a AimState : on garde camera et verrouillage
|
var _keep_aim : bool = false #true quand on retourne a AimState : on garde camera et verrouillage
|
||||||
var _pokemon : PokemonInstance = null
|
var _pokemon : PokemonInstance = null
|
||||||
var _target : Variant = null #AimTarget verrouille au moment du lancer
|
var _target : Variant = null #AimTarget verrouille au moment du relachement
|
||||||
var _free_aim_point : Vector3 = Vector3.ZERO
|
var _free_aim_point : Vector3 = Vector3.ZERO
|
||||||
|
var _came_from_crouch : bool = false #true si le lancer vient du crouch (directement, ou via Aim declenche depuis le crouch)
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
_ensure_action(throw_action, func():
|
||||||
|
var trigger := InputEventJoypadMotion.new()
|
||||||
|
trigger.axis = JOY_AXIS_TRIGGER_RIGHT
|
||||||
|
trigger.axis_value = 1.0
|
||||||
|
InputMap.action_add_event(throw_action, trigger)
|
||||||
|
var click := InputEventMouseButton.new()
|
||||||
|
click.button_index = MOUSE_BUTTON_LEFT
|
||||||
|
InputMap.action_add_event(throw_action, click))
|
||||||
|
_ensure_action(cancel_action, func():
|
||||||
|
var pad := InputEventJoypadButton.new()
|
||||||
|
pad.button_index = JOY_BUTTON_B
|
||||||
|
InputMap.action_add_event(cancel_action, pad)
|
||||||
|
var click := InputEventMouseButton.new()
|
||||||
|
click.button_index = MOUSE_BUTTON_RIGHT
|
||||||
|
InputMap.action_add_event(cancel_action, click))
|
||||||
|
|
||||||
|
func _ensure_action(action : StringName, add_events : Callable) -> void:
|
||||||
|
if InputMap.has_action(action): return
|
||||||
|
InputMap.add_action(action)
|
||||||
|
add_events.call()
|
||||||
|
|
||||||
func enter(play_char_ref : CharacterBody3D) -> void:
|
func enter(play_char_ref : CharacterBody3D) -> void:
|
||||||
play_char = play_char_ref
|
play_char = play_char_ref
|
||||||
_elapsed = 0.0
|
_elapsed = 0.0
|
||||||
|
_released = false
|
||||||
_thrown = false
|
_thrown = false
|
||||||
_keep_aim = false
|
_keep_aim = false
|
||||||
|
|
||||||
|
#curr_state_name n'est pas encore mis a jour a ce stade : il reflete encore l'etat qu'on quitte
|
||||||
|
var previous : String = play_char.state_machine.curr_state_name
|
||||||
|
if previous == "Crouch":
|
||||||
|
_came_from_crouch = true
|
||||||
|
elif previous == "Aim":
|
||||||
|
var aim : Node = play_char.state_machine.states.get("aimstate")
|
||||||
|
_came_from_crouch = aim != null and aim.came_from_crouch
|
||||||
|
else:
|
||||||
|
_came_from_crouch = false
|
||||||
|
|
||||||
_pokemon = GameData.get_selected_pokemon()
|
_pokemon = GameData.get_selected_pokemon()
|
||||||
_target = play_char.aim_target if is_instance_valid(play_char.aim_target) else null
|
_target = null
|
||||||
_free_aim_point = _compute_free_aim_point() #visee libre : le point est fige au moment ou on appuie
|
_free_aim_point = Vector3.ZERO
|
||||||
|
|
||||||
play_char.floor_snap_length = 1.0
|
play_char.floor_snap_length = 1.0
|
||||||
#play_char.godot_plush_skin.set_state("throw")
|
#play_char.godot_plush_skin.set_state("throw")
|
||||||
|
|
@ -56,12 +97,24 @@ func physics_update(delta : float) -> void:
|
||||||
if applies(): return
|
if applies(): return
|
||||||
|
|
||||||
play_char.gravity_apply(delta)
|
play_char.gravity_apply(delta)
|
||||||
slow_down(delta)
|
|
||||||
|
|
||||||
if _pokemon == null:
|
if _pokemon == null:
|
||||||
|
slow_down(delta)
|
||||||
finish() #rien a lancer (equipe vide ou tous K.O.)
|
finish() #rien a lancer (equipe vide ou tous K.O.)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
#phase 1 : charge, tant que RT est maintenue
|
||||||
|
if !_released:
|
||||||
|
charge(delta)
|
||||||
|
return
|
||||||
|
|
||||||
|
#phase 2 : windup puis recovery
|
||||||
|
slow_down(delta)
|
||||||
|
|
||||||
|
if !_thrown and Input.is_action_just_pressed(cancel_action):
|
||||||
|
finish() #annule avant que la balle parte
|
||||||
|
return
|
||||||
|
|
||||||
_elapsed += delta
|
_elapsed += delta
|
||||||
if !_thrown and _elapsed >= windup_time:
|
if !_thrown and _elapsed >= windup_time:
|
||||||
throw_ball()
|
throw_ball()
|
||||||
|
|
@ -74,6 +127,35 @@ func applies() -> bool:
|
||||||
return true
|
return true
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
#---------- charge ----------
|
||||||
|
|
||||||
|
func charge(delta : float) -> void:
|
||||||
|
if Input.is_action_just_pressed(cancel_action):
|
||||||
|
finish() #annule : rien n'est lance
|
||||||
|
return
|
||||||
|
|
||||||
|
if !Input.is_action_pressed(throw_action):
|
||||||
|
release()
|
||||||
|
return
|
||||||
|
|
||||||
|
move_while_charging(delta)
|
||||||
|
|
||||||
|
func release() -> void:
|
||||||
|
#RT relachee : on fige la cible et le point vise, puis le windup demarre
|
||||||
|
_released = true
|
||||||
|
_elapsed = 0.0
|
||||||
|
_target = play_char.aim_target if is_instance_valid(play_char.aim_target) else null
|
||||||
|
_free_aim_point = _compute_free_aim_point()
|
||||||
|
|
||||||
|
func move_while_charging(delta : float) -> void:
|
||||||
|
play_char.move_dir = Input.get_vector(play_char.move_left_action, play_char.move_right_action, play_char.move_forward_action, play_char.move_backward_action).rotated(-play_char.cam_holder.global_rotation.y)
|
||||||
|
|
||||||
|
if play_char.move_dir and play_char.is_on_floor():
|
||||||
|
play_char.velocity.x = lerp(play_char.velocity.x, play_char.move_dir.x * charge_move_speed, charge_move_accel * delta)
|
||||||
|
play_char.velocity.z = lerp(play_char.velocity.z, play_char.move_dir.y * charge_move_speed, charge_move_accel * delta)
|
||||||
|
else:
|
||||||
|
slow_down(delta)
|
||||||
|
|
||||||
func slow_down(delta : float) -> void:
|
func slow_down(delta : float) -> void:
|
||||||
play_char.velocity.x = lerp(play_char.velocity.x, 0.0, play_char.move_deccel * delta)
|
play_char.velocity.x = lerp(play_char.velocity.x, 0.0, play_char.move_deccel * delta)
|
||||||
play_char.velocity.z = lerp(play_char.velocity.z, 0.0, play_char.move_deccel * delta)
|
play_char.velocity.z = lerp(play_char.velocity.z, 0.0, play_char.move_deccel * delta)
|
||||||
|
|
@ -81,9 +163,16 @@ func slow_down(delta : float) -> void:
|
||||||
func finish() -> void:
|
func finish() -> void:
|
||||||
if Input.is_action_pressed(aim_action):
|
if Input.is_action_pressed(aim_action):
|
||||||
_keep_aim = true
|
_keep_aim = true
|
||||||
|
#AimState ne verra que "Throw" comme etat precedent : on lui transmet l'origine crouch
|
||||||
|
var aim : Node = play_char.state_machine.states.get("aimstate")
|
||||||
|
if aim: aim.came_from_crouch = _came_from_crouch
|
||||||
transitioned.emit(self, "AimState")
|
transitioned.emit(self, "AimState")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if _came_from_crouch:
|
||||||
|
transitioned.emit(self, "CrouchState")
|
||||||
|
return
|
||||||
|
|
||||||
var dir : Vector2 = Input.get_vector(play_char.move_left_action, play_char.move_right_action, play_char.move_forward_action, play_char.move_backward_action)
|
var dir : Vector2 = Input.get_vector(play_char.move_left_action, play_char.move_right_action, play_char.move_forward_action, play_char.move_backward_action)
|
||||||
transitioned.emit(self, play_char.walk_or_run if dir != Vector2.ZERO else "IdleState")
|
transitioned.emit(self, play_char.walk_or_run if dir != Vector2.ZERO else "IdleState")
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue