Voir le sujet précédent :: Voir le sujet suivant |
Auteur |
Message |
Max Floodeur prématuré
Inscrit le: 13 Jan 2009 Messages: 550 Sujets: 47 Spécialité en worldedit: La partie déclencheurs sauf le GUI.
|
Posté le: 06/08/12 17:48 Sujet du message: Problème de désynch avec le son |
|
|
Bonjour,
J'ai un problème de désynchronisation des joueurs.
Le principe est de jouer un son pour un joueur, et un autre son pour tous les autres. Quand un héros meurt, son owner entend "notre héros est mort" et les autres joueurs entendent "un héros allié est tombé".
Jass: | private function GetRandomSoundHeroDies takes nothing returns sound
local integer n = GetRandomInt(0, 3)
if (n == 0) then
return gg_snd_heroDies0
elseif (n == 1) then
return gg_snd_heroDies1
elseif (n == 2) then
return gg_snd_heroDies2
else
return gg_snd_heroDies3
endif
endfunction
private function GetRandomSoundAllyHeroDies takes nothing returns sound
local integer n = GetRandomInt(0, 3)
if (n == 0) then
return gg_snd_allyHeroDies0
elseif (n == 1) then
return gg_snd_allyHeroDies1
elseif (n == 2) then
return gg_snd_allyHeroDies2
else
return gg_snd_allyHeroDies3
endif
endfunction
private function IsSoundHeroDiesPlaying takes nothing returns boolean
return (GetSoundIsPlaying(gg_snd_heroDies0) or GetSoundIsPlaying(gg_snd_heroDies1) or GetSoundIsPlaying(gg_snd_heroDies2) or GetSoundIsPlaying(gg_snd_heroDies3))
endfunction
private function IsSoundAllyHeroDiesPlaying takes nothing returns boolean
return (GetSoundIsPlaying(gg_snd_allyHeroDies0) or GetSoundIsPlaying(gg_snd_allyHeroDies1) or GetSoundIsPlaying(gg_snd_allyHeroDies2) or GetSoundIsPlaying(gg_snd_allyHeroDies3))
endfunction
function PlaySoundHeroDies takes player fallenPlayer returns nothing
if (GetLocalPlayer() == fallenPlayer) then
if (not IsSoundHeroDiesPlaying() and not IsSoundAllyHeroDiesPlaying()) then
call StartSound(GetRandomSoundHeroDies())
endif
else
if (not IsSoundHeroDiesPlaying() and not IsSoundAllyHeroDiesPlaying()) then
call StartSound(GetRandomSoundAllyHeroDies())
endif
endif
endfunction |
On appelle donc la fonction PlaySoundHeroDies. Mais ça crée des désynch, et je ne comprends pas pourquoi. Il existe pourtant bien la fonction StartSoundForPlayerBJ :
Jass: | function StartSoundForPlayerBJ takes player whichPlayer, sound soundHandle returns nothing
if (whichPlayer == GetLocalPlayer()) then
call StartSound(soundHandle)
endif
endfunction |
et je ne vois pas pourquoi jouer un son pour un joueur et pas un autre créerait des désynchronisations.
Help anyone :p.
edit : petite précision, après les tests j'me suis rendu compte que j'étais le seul à être désynchronisé par rapport aux autre, et que j'étais également le seul à avoir le son d'activé. _________________
|
|
Revenir en haut |
|
|
Tirlititi
Inscrit le: 21 Fév 2010 Messages: 1785 Sujets: 22 Spécialité en worldedit: La modestie Médailles: 1 (En savoir plus...)
|
Posté le: 06/08/12 18:39 Sujet du message: |
|
|
C'est sans doute à cause de tes "IsSoundHeroDiesPlaying", je suppose. Essaies en utilisant un timer : tu empêches les sons d'être rejoué pendant 5 secondes après l'appel de "PlaySoundHeroDie".
Mais ça me parait un peu étrange quand même. Tu es sûr que c'est cette fonction qui désync? _________________
|
|
Revenir en haut |
|
|
Troll-Brain Ri1kamoua
Inscrit le: 23 Aoû 2007 Messages: 7143 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
|
Posté le: 06/08/12 19:06 Sujet du message: |
|
|
Normalement ca ne devrait pas desync, du moment que tu n'utilises pas ces fonctions dans une condition de trigger (et encore c'est à tester), ou "wait for sound", ou enfin que tu ne cherches pas à les utiliser comme si le résultat était synchrone.
Voir peut être aussi si tu utilises la fonction native qui détruit le son une fois joué (KillSoundWhenDone ou quelque chose du style).
Essaye en jouant le son pour tous les joueurs mais avec le volume à 0 pour tout le monde sauf le joueur voulu.
Sinon, rien d'exceptionnel mais pour ce genre de code local peut être que ceci te conviendrait. _________________
|
|
Revenir en haut |
|
|
Max Floodeur prématuré
Inscrit le: 13 Jan 2009 Messages: 550 Sujets: 47 Spécialité en worldedit: La partie déclencheurs sauf le GUI.
|
Posté le: 06/08/12 20:11 Sujet du message: |
|
|
Citation: | Tu es sûr que c'est cette fonction qui désync? |
Voici du code que je n'ai pas posté :
Jass: | //! textmacro DisplayDeathMessagePlayer_function takes n
function DisplayDeathMessagePlayer_$n$ takes nothing returns nothing
call PlaySoundHeroDies(Player($n$))
call Text_A_timed(MESSAGE_DURATION, udg_colorCode[$n$] + GetPlayerName(Player($n$)) + "|r has fallen.")
call DestroyTimer(GetExpiredTimer())
endfunction
//! endtextmacro
//! runtextmacro DisplayDeathMessagePlayer_function("0")
//! runtextmacro DisplayDeathMessagePlayer_function("1")
//! runtextmacro DisplayDeathMessagePlayer_function("2")
//! runtextmacro DisplayDeathMessagePlayer_function("3")
//! runtextmacro DisplayDeathMessagePlayer_function("4")
//! runtextmacro DisplayDeathMessagePlayer_function("5")
//! runtextmacro DisplayDeathMessagePlayer_function("6")
//! runtextmacro DisplayDeathMessagePlayer_function("7")
//! runtextmacro DisplayDeathMessagePlayer_function("8")
//! runtextmacro DisplayDeathMessagePlayer_function("9")
//! runtextmacro DisplayDeathMessagePlayer_function("10")
//! runtextmacro DisplayDeathMessagePlayer_function("11")
function DisplayDeathMessagePlayer takes player p returns nothing
local integer n = GetPlayerId(p)
//! textmacro RunDisplayDeathMessagePlayer takes n
if (n == $n$) then
call TimerStart(CreateTimer(), TIME_BETWEEN_DEATH_AND_MESSAGE, false, function DisplayDeathMessagePlayer_$n$)
endif
//! endtextmacro
//! runtextmacro RunDisplayDeathMessagePlayer("0")
//! runtextmacro RunDisplayDeathMessagePlayer("1")
//! runtextmacro RunDisplayDeathMessagePlayer("2")
//! runtextmacro RunDisplayDeathMessagePlayer("3")
//! runtextmacro RunDisplayDeathMessagePlayer("4")
//! runtextmacro RunDisplayDeathMessagePlayer("5")
//! runtextmacro RunDisplayDeathMessagePlayer("6")
//! runtextmacro RunDisplayDeathMessagePlayer("7")
//! runtextmacro RunDisplayDeathMessagePlayer("8")
//! runtextmacro RunDisplayDeathMessagePlayer("9")
//! runtextmacro RunDisplayDeathMessagePlayer("10")
//! runtextmacro RunDisplayDeathMessagePlayer("11")
endfunction |
La fonction DisplayDeathMessagePlayer est appelée à chaque fois qu'un héros meurt. Si je commente l'appel à cette fonction il n'y a plus de désynchronisation. _________________
|
|
Revenir en haut |
|
|
Tirlititi
Inscrit le: 21 Fév 2010 Messages: 1785 Sujets: 22 Spécialité en worldedit: La modestie Médailles: 1 (En savoir plus...)
|
Posté le: 06/08/12 22:14 Sujet du message: |
|
|
Ben ouais, ben ça a pas l'air d'être ça ^^.
Ben je vois pas, essaies ce que jt'ai dit (un timer plutôt que tes fonctions) et les méthodes de TB, sait-on jamais. _________________
|
|
Revenir en haut |
|
|
Max Floodeur prématuré
Inscrit le: 13 Jan 2009 Messages: 550 Sujets: 47 Spécialité en worldedit: La partie déclencheurs sauf le GUI.
|
Posté le: 06/08/12 22:20 Sujet du message: |
|
|
Tirliti a raison concernant les causes de la désynch. Si je commente les conditions de PlaySoundHeroDies, ça ne désynch plus :
Jass: | function PlaySoundHeroDies takes player fallenPlayer returns nothing
if (GetLocalPlayer() == fallenPlayer) then
//if (not IsSoundHeroDiesPlaying() and not IsSoundAllyHeroDiesPlaying()) then
call StartSound(GetRandomSoundHeroDies())
//endif
else
//if (not IsSoundHeroDiesPlaying() and not IsSoundAllyHeroDiesPlaying()) then
call StartSound(GetRandomSoundAllyHeroDies())
//endif
endif
endfunction |
Essayer la technique "en jouant le son pour tous les joueurs mais avec le volume à 0 pour tout le monde sauf le joueur voulu" ne me bottait pas trop, car trop bidouillage à mon goût, j'ai préféré utiliser un timer. Skip "GetSoundIsPlaying" donne un très bon résultat, pas de désynchro pour un code que je trouve plus propre.
Voici donc ma nouvelle bibliothèque, au complet :
Jass: | library MessageHeroDies needs Text
globals
private constant real MESSAGE_DURATION = 10
private constant real TIME_BETWEEN_DEATH_AND_MESSAGE = 5
private timer timerSonJoue = CreateTimer()
private boolean isSoundPlaying = false
private real DUREE_SON = 3
endglobals
private function GetRandomSoundHeroDies takes nothing returns sound
local integer n = GetRandomInt(0, 3)
if (n == 0) then
return gg_snd_heroDies0
elseif (n == 1) then
return gg_snd_heroDies1
elseif (n == 2) then
return gg_snd_heroDies2
else
return gg_snd_heroDies3
endif
endfunction
private function GetRandomSoundAllyHeroDies takes nothing returns sound
local integer n = GetRandomInt(0, 3)
if (n == 0) then
return gg_snd_allyHeroDies0
elseif (n == 1) then
return gg_snd_allyHeroDies1
elseif (n == 2) then
return gg_snd_allyHeroDies2
else
return gg_snd_allyHeroDies3
endif
endfunction
private function SoundEnd takes nothing returns nothing
set isSoundPlaying = false
endfunction
private function PlaySoundHeroDies takes player fallenPlayer returns nothing
if (not isSoundPlaying) then
if (GetLocalPlayer() == fallenPlayer) then
call StartSound(GetRandomSoundHeroDies())
else
call StartSound(GetRandomSoundAllyHeroDies())
endif
set isSoundPlaying = true
call TimerStart(timerSonJoue, DUREE_SON, false, function SoundEnd)
endif
endfunction
//! textmacro DisplayDeathMessagePlayer_function takes n
private function DisplayDeathMessagePlayer_$n$ takes nothing returns nothing
call PlaySoundHeroDies(Player($n$))
call Text_A_timed(MESSAGE_DURATION, udg_colorCode[$n$] + GetPlayerName(Player($n$)) + "|r has fallen.")
call DestroyTimer(GetExpiredTimer())
endfunction
//! endtextmacro
//! runtextmacro DisplayDeathMessagePlayer_function("0")
//! runtextmacro DisplayDeathMessagePlayer_function("1")
//! runtextmacro DisplayDeathMessagePlayer_function("2")
//! runtextmacro DisplayDeathMessagePlayer_function("3")
//! runtextmacro DisplayDeathMessagePlayer_function("4")
//! runtextmacro DisplayDeathMessagePlayer_function("5")
//! runtextmacro DisplayDeathMessagePlayer_function("6")
//! runtextmacro DisplayDeathMessagePlayer_function("7")
//! runtextmacro DisplayDeathMessagePlayer_function("8")
//! runtextmacro DisplayDeathMessagePlayer_function("9")
//! runtextmacro DisplayDeathMessagePlayer_function("10")
//! runtextmacro DisplayDeathMessagePlayer_function("11")
function DisplayDeathMessagePlayer takes player p returns nothing
local integer n = GetPlayerId(p)
//! textmacro RunDisplayDeathMessagePlayer takes n
if (n == $n$) then
call TimerStart(CreateTimer(), TIME_BETWEEN_DEATH_AND_MESSAGE, false, function DisplayDeathMessagePlayer_$n$)
endif
//! endtextmacro
//! runtextmacro RunDisplayDeathMessagePlayer("0")
//! runtextmacro RunDisplayDeathMessagePlayer("1")
//! runtextmacro RunDisplayDeathMessagePlayer("2")
//! runtextmacro RunDisplayDeathMessagePlayer("3")
//! runtextmacro RunDisplayDeathMessagePlayer("4")
//! runtextmacro RunDisplayDeathMessagePlayer("5")
//! runtextmacro RunDisplayDeathMessagePlayer("6")
//! runtextmacro RunDisplayDeathMessagePlayer("7")
//! runtextmacro RunDisplayDeathMessagePlayer("8")
//! runtextmacro RunDisplayDeathMessagePlayer("9")
//! runtextmacro RunDisplayDeathMessagePlayer("10")
//! runtextmacro RunDisplayDeathMessagePlayer("11")
endfunction
endlibrary |
Si vous voyez comment l'améliorer dites-le moi .
En tous cas merci de votre aide.
Concernant ta bibliothèque LocalHelper TB, j'ai lu ton post, mais j'ai dû mal à comprendre l'avantage de son utilisation. :/ _________________
|
|
Revenir en haut |
|
|
Troll-Brain Ri1kamoua
Inscrit le: 23 Aoû 2007 Messages: 7143 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
|
Posté le: 06/08/12 23:00 Sujet du message: |
|
|
Et Dieu maudit le jour où il inventa les if/then, et Vexorian les textmacros.
Citation: | Concernant ta bibliothèque LocalHelper TB, j'ai lu ton post, mais j'ai dû mal à comprendre l'avantage de son utilisation. :/
|
C'est parce que "you don't speak english very well" :p _________________
|
|
Revenir en haut |
|
|
Max Floodeur prématuré
Inscrit le: 13 Jan 2009 Messages: 550 Sujets: 47 Spécialité en worldedit: La partie déclencheurs sauf le GUI.
|
Posté le: 07/08/12 03:38 Sujet du message: |
|
|
Citation: | Et Dieu maudit le jour où il inventa les if/then, et Vexorian les textmacros. |
Vois-tu un meilleur moyen de faire ? Je suis toute ouïe.
Citation: | C'est parce que "you don't speak english very well" :p |
Sans doute. Et il faudrait que je prenne plus le temps de me plonger dans le code. _________________
|
|
Revenir en haut |
|
|
Troll-Brain Ri1kamoua
Inscrit le: 23 Aoû 2007 Messages: 7143 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
|
Posté le: 07/08/12 23:21 Sujet du message: |
|
|
Script écrit sous jasscraft (pas vérifié) :
Jass: | library MessageHeroDies requires Text, LocalHelper, TimerUtilsEx
globals
private constant real MESSAGE_DURATION = 10
private constant real TIME_BETWEEN_DEATH_AND_MESSAGE = 5
private timer timerSonJoue = CreateTimer()
private boolean isSoundPlaying = false
private real DUREE_SON = 3
endglobals
private function GetRandomSoundHeroDies takes nothing returns sound
local integer n = GetRandomInt(0, 3)
if (n == 0) then
return gg_snd_heroDies0
elseif (n == 1) then
return gg_snd_heroDies1
elseif (n == 2) then
return gg_snd_heroDies2
else
return gg_snd_heroDies3
endif
endfunction
private function GetRandomSoundAllyHeroDies takes nothing returns sound
local integer n = GetRandomInt(0, 3)
if (n == 0) then
return gg_snd_allyHeroDies0
elseif (n == 1) then
return gg_snd_allyHeroDies1
elseif (n == 2) then
return gg_snd_allyHeroDies2
else
return gg_snd_allyHeroDies3
endif
endfunction
private function SoundEnd takes nothing returns nothing
set isSoundPlaying = false
endfunction
private function PlaySoundHeroDies takes player fallenPlayer returns nothing
if (not isSoundPlaying) then
if IsForPlayer( fallenPlayer ) then
call StartSound(GetRandomSoundHeroDies())
else
call StartSound(GetRandomSoundAllyHeroDies())
endif
set isSoundPlaying = true
call TimerStart(timerSonJoue, DUREE_SON, false, function SoundEnd)
endif
endfunction
private function DisplayDeathMessagePlayer takes nothing returns nothing
local integer n = ReleaseTimer(GetExpiredTimer())
call PlaySoundHeroDies(Player(n))
call Text_A_timed(MESSAGE_DURATION, udg_colorCode[n] + GetPlayerName(Player(n)) + "|r has fallen.")
endfunction
function DisplayDeathMessagePlayer takes player p returns nothing
call TimerStart(TimerNewEx(GetPlayerId(p)), TIME_BETWEEN_DEATH_AND_MESSAGE, false, function DisplayDeathMessagePlayer)
endfunction
endlibrary |
Requirements :
TimerUtilsEx
Ma librairie LocalHelper (mais c'était juste un ex concret d'utilisation, y'a rien de nécessaire)
Cette version de TimerUtils est 100 fois mieux que celle de Vexorian, car actuellement elle fonctionne comme elle devrait, pas comme celle de Vexo.
Enfin perso j'utilisais une library perso beaucoup moins verbeuse (une seule fonction qui "créé", démarre le timer, lie la donné entière)
Pour en revenir à ma librairie LocalHelper, c'est juste une façon moins verbeuse d’exécuter du code localement, perso ca m'a toujours gaver de devoir écrire à chaque fois if GetLocalPlayer() == <player> ...
Quand c'est pour un seul joueur la différence n'est pas forcément flagrante, par contre si tu veux le faire pour X joueurs en même temps, alors là ça devient carrément sexy, comme dans l'exemple que j'ai donné avec ma library.
Ah et pour les sons, il me semble qu'il y a plein de limitations, du genre on ne peut lire un son qui est déjà en cours de lecture, il faut peut être aussi le "preload", etc ...
Bref j'en sais pas beaucoup plus mais c'est ce que j'ai lu dans mes pérégrinations sur la toile warcraftienne.
Peut être que tu pourrais jeter un oeil attentif sur ceci
Même si la ressource ne n'intéresse pas, y'a probablement des commentaires intéressants.
Pour ton code il serait aussi plus judicieux d'utiliser une global sound array, comme cela ton code est plus modulable, plus besoin de construire et modifier un if/then/elseif... à chaque modif.
Cela dit c'est sur que y'a peu de sons à gérer ici, m'enfin ca reste une bonne pratique je trouves. _________________
|
|
Revenir en haut |
|
|
kungfu-sheep Anomalie floodiforme
Inscrit le: 14 Avr 2011 Messages: 1846 Sujets: 119 Spécialité en worldedit: fonctions paramétriques, équation de mouvement.
|
|
Revenir en haut |
|
|
Troll-Brain Ri1kamoua
Inscrit le: 23 Aoû 2007 Messages: 7143 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
|
|
Revenir en haut |
|
|
Max Floodeur prématuré
Inscrit le: 13 Jan 2009 Messages: 550 Sujets: 47 Spécialité en worldedit: La partie déclencheurs sauf le GUI.
|
Posté le: 08/08/12 21:53 Sujet du message: |
|
|
TB a écrit: | Enfin perso j'utilisais une library perso beaucoup moins verbeuse (une seule fonction qui "créé", démarre le timer, lie la donné entière) |
C'est vrai que j'aurais pu faire comme ça, mais je n'avais pas envie de créé une hashtable rien que pour ça.
TB a écrit: | Pour en revenir à ma librairie LocalHelper, c'est juste une façon moins verbeuse d’exécuter du code localement, perso ca m'a toujours gaver de devoir écrire à chaque fois if GetLocalPlayer() == <player> ...
Quand c'est pour un seul joueur la différence n'est pas forcément flagrante, par contre si tu veux le faire pour X joueurs en même temps, alors là ça devient carrément sexy, comme dans l'exemple que j'ai donné avec ma library. |
OK.
TB a écrit: | Pour ton code il serait aussi plus judicieux d'utiliser une global sound array, comme cela ton code est plus modulable, plus besoin de construire et modifier un if/then/elseif... à chaque modif.
Cela dit c'est sur que y'a peu de sons à gérer ici, m'enfin ca reste une bonne pratique je trouves. |
J'y ai pensé, j'y ai pensé, mais en principe ça ne devrait pas bouger : c'est juste les sons de héros morts pour les quatre races. _________________
|
|
Revenir en haut |
|
|
Troll-Brain Ri1kamoua
Inscrit le: 23 Aoû 2007 Messages: 7143 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
|
|
Revenir en haut |
|
|
|