Sprites that do not return to their initial state with certain combinations

Hi I am recreating on Godot one of my first games that I created with another engine and I encounter a problem. On certain key combinations the Sprites do not return to their original sprite and the voiceover does not restart. Here is the code.

Godot Issue Video

extends Node2D

Variables pour les scores

var player_score = 0
var cpc_score = 0

Variables pour les choix

var player_choice = “”
var cpc_choice = “”

Variable pour activer/désactiver les entrées

var inputs_enabled = false # Désactivé par défaut

Variable pour vérifier si un tour est en cours

var round_in_progress = false

Chemins des ressources

const SPRITES = {
“attente_joueur”: “res://attentejoueurun.png”, # Chemin corrigé
“attente_cpc”: “res://attentecpc.png”, # Chemin corrigé
“papier”: “res://papierimage.png”,
“ciseaux”: “res://ciseauximage.png”,
“roche”: “res://rocheimage.png”,
“gun”: “res://gunimage.png”
}

const SONS = {
“papier”: “res://smsound.wav”,
“ciseaux”: “res://scissorsoundtwo.wav”,
“roche”: “res://rockfallsoundtrois.wav”,
“gun”: “res://gunsoundtrois.wav”
}

Références aux nœuds de la scène

@onready var attentejoueurun = $Attentejoueurun
@onready var attentecpc = $Attentecpc
@onready var audio_player = $RPCBGAudio
@onready var audio_player_cpc = $AudioStreamPlayerCPC
@onready var label_joueur = $Label
@onready var label_cpc = $Label2

Fonction prête

func _ready():
# Désactiver les boutons immédiatement au démarrage
enable_buttons(false)
inputs_enabled = false

# Initialiser les sprites d'attente
reset_sprites()

# Connecter les boutons à leurs fonctions
$Papierbutton.pressed.connect(start_round.bind("papier"))
$Ciseaubutton.pressed.connect(start_round.bind("ciseaux"))
$Rochebutton.pressed.connect(start_round.bind("roche"))
$Gunbutton.pressed.connect(start_round.bind("gun"))

# Jouer la voix off "roche papier ciseaux balle de fusil"
play_voice_off()

Fonction pour jouer la voix off

func play_voice_off():
# Vérifier si un joueur a déjà gagné
if player_score >= 8 or cpc_score >= 8:
return # Ne pas jouer la voix off si le jeu est terminé

# Attendre que le nœud soit dans l'arbre de scène
if not is_inside_tree():
	await tree_entered  # Attendre que le nœud soit ajouté à l'arbre de scène

var voice_off_path = "res://rockpaperscissorsbulletgun.mp3"
if ResourceLoader.exists(voice_off_path):
	audio_player.stream = load(voice_off_path)
	audio_player.play()
	await audio_player.finished  # Attendre la fin de la voix off
	enable_buttons(true)  # Réactiver les boutons
	inputs_enabled = true  # Réactiver les entrées
else:
	print("Erreur : Le fichier audio n'existe pas à l'emplacement : ", voice_off_path)

Fonction pour réinitialiser les sprites

func reset_sprites():
if is_instance_valid(attentejoueurun) and is_instance_valid(attentecpc):
attentejoueurun.texture = load(SPRITES[“attente_joueur”])
attentecpc.texture = load(SPRITES[“attente_cpc”])
print(“Sprites réinitialisés.”)
else:
print(“Erreur : Les sprites ne sont pas valides.”)

Fonction pour activer/désactiver les boutons

func enable_buttons(enabled):
$Papierbutton.disabled = !enabled
$Ciseaubutton.disabled = !enabled
$Rochebutton.disabled = !enabled
$Gunbutton.disabled = !enabled

Fonction pour comparer les choix

func compare_choices(player_choice, cpc_choice):
if player_choice == cpc_choice:
return “Égalité”

match player_choice:
	"papier":
		if cpc_choice == "roche":
			return "Joueur gagne"
		elif cpc_choice == "ciseaux":
			return "CPC gagne"
		elif cpc_choice == "gun":
			return "CPC gagne"  # Gun > Papier
	"ciseaux":
		if cpc_choice == "papier":
			return "Joueur gagne"
		elif cpc_choice == "roche":
			return "CPC gagne"
		elif cpc_choice == "gun":
			return "CPC gagne"  # Gun > Ciseaux
	"roche":
		if cpc_choice == "ciseaux":
			return "Joueur gagne"
		elif cpc_choice == "papier":
			return "CPC gagne"
		elif cpc_choice == "gun":
			return "Joueur gagne"  # Roche > Gun
	"gun":
		if cpc_choice == "papier":
			return "Joueur gagne"  # Gun > Papier
		elif cpc_choice == "ciseaux":
			return "Joueur gagne"  # Gun > Ciseaux
		elif cpc_choice == "roche":
			return "CPC gagne"  # Roche > Gun

return "Erreur"

Fonction pour démarrer un tour

func start_round(choice):
if round_in_progress: # Empêcher les entrées multiples
return

round_in_progress = true  # Marquer qu'un tour est en cours
inputs_enabled = false  # Désactiver les entrées
enable_buttons(false)  # Désactiver les boutons

player_choice = choice
cpc_choice = ["papier", "ciseaux", "roche", "gun"][randi() % 4]  # Choix aléatoire du CPC

print("Choix du joueur : ", player_choice)
print("Choix du CPC : ", cpc_choice)

# Mettre à jour les sprites
update_sprites(player_choice, cpc_choice)

# Jouer les sons du joueur et du CPC en même temps
play_sound(player_choice, audio_player)
play_sound(cpc_choice, audio_player_cpc)

# Attendre que les deux sons soient terminés
await audio_player.finished
await audio_player_cpc.finished

print("Les sons sont terminés. Réinitialisation des sprites.")

# Réinitialiser les sprites après la fin des sons
reset_sprites()

# Comparer les choix et mettre à jour les scores
var result = compare_choices(player_choice, cpc_choice)
print("Résultat du tour : ", result)
update_scores(result)

# Vérifier si un joueur a gagné
check_win_condition()

# Rejouer la voix off
play_voice_off()

round_in_progress = false  # Réactiver les entrées après la fin du tour

Fonction pour mettre à jour les sprites

func update_sprites(player_choice, cpc_choice):
if is_instance_valid(attentejoueurun) and is_instance_valid(attentecpc):
attentejoueurun.texture = load(SPRITES[player_choice])
attentecpc.texture = load(SPRITES[cpc_choice])
else:
print(“Erreur : Les sprites ne sont pas valides.”)

Fonction pour jouer le son associé à l’élément

func play_sound(choice, player):
var sound_path = SONS[choice]
if ResourceLoader.exists(sound_path):
player.stream = load(sound_path)
player.play()
print("Son joué : ", choice)
else:
print("Erreur : Le fichier audio n’existe pas à l’emplacement : ", sound_path)
# Si le son ne peut pas être joué, forcer la réinitialisation
reset_sprites()
play_voice_off()

Fonction pour mettre à jour les scores

func update_scores(result):
if result == “Joueur gagne”:
player_score += 1
elif result == “CPC gagne”:
cpc_score += 1
# Mettre à jour les labels des scores (uniquement les chiffres)
label_joueur.text = str(player_score)
label_cpc.text = str(cpc_score)

Fonction pour vérifier la condition de victoire

func check_win_condition():
if player_score >= 8:
label_joueur.text = str(player_score) # Afficher le score final
audio_player.stop() # Arrêter la voix off
await get_tree().create_timer(1.0).timeout # Attendre 1 seconde
get_tree().change_scene_to_file(“res://youwin.tscn”)
elif cpc_score >= 8:
label_cpc.text = str(cpc_score) # Afficher le score final
audio_player.stop() # Arrêter la voix off
await get_tree().create_timer(1.0).timeout # Attendre 1 seconde
get_tree().change_scene_to_file(“res://youloose.tscn”)

Fonction pour revenir à l’écran titre

func return_to_title_screen():
get_tree().change_scene_to_file(“res://ecrantitre.tscn”)

Fonction pour gérer les entrées de la manette et du clavier

func _input(event):
# Gérer la touche Quitter à tout moment
if event.is_action_pressed(“ui_quit”): # Bouton 4/Select ou touche Escape
return_to_title_screen()
return # Quitter la fonction pour éviter de traiter d’autres entrées

# Gérer les autres entrées uniquement si elles sont activées
if not inputs_enabled:
	return  # Ignorer les autres entrées si elles sont désactivées

if event.is_action_pressed("ui_papier"):  # Bouton A/0
	start_round("papier")
elif event.is_action_pressed("ui_ciseaux"):  # Bouton B/1
	start_round("ciseaux")
elif event.is_action_pressed("ui_roche"):  # Bouton X/2
	start_round("roche")
elif event.is_action_pressed("ui_gun"):  # Bouton Y/3
	start_round("gun")

Finally I found the solution. Indeed it was due to the sound of the elements that do not have the same duration which can cause a bug during certain combinations. If you have a code that works well or you know how to solve this problem otherwise Do not hesitate to share it with me.