GTAOnline.net
San Andreas Multiplayer (sa:mp) => Scripting SA-MP [Pawn center] => Discussion démarrée par: Jens84 le 09 Novembre 2008, 10:48:06
-
Bonjour, je voudrais savoir comment, en utilisant (ou pas) la callback "OnPlayerKeyStateChange", je pourrais executer une action, si la touche définie dans la callback est maintenue pendant un certain temps donné.
Merci d'avance pour vos réponses.
Jens84
-
Salut,
malheureusement, pour faire ce que tu veut,
il faut utiliser un timer et un GetPlayerKeys,
comme son nom l'indique, la callback OnPlayerKeyStateChange est appelé quand le joueur CHANGE de touche
++Sim++
-
Ok pour la callback je comprends. Cependant je ne vois pas comment on peut utiliser un timer pour faire mon action, car un timer sert bien à exécuter une action au bout d'un certain temps, je ne vois pas comment l'utiliser autrement pour effectuer mon action...
Merci pour vos réponses !
-
En faite tu lance le timer quand le gars appuis sur la touche, et tu met en place une variable, si le joueur relâche la touche, la variable re bascule a 0 et arrêt le timer, ce qui fait que l'action ne se produit que si le joueur maintient la touche ^^ Happy !!! :laugh
-
En utilisant un GetPlayerKeys et un timer, on risque de "tomber" dans le travers suivant :
Le joueur appuie sur la touche une fois puis il appuie une deuxième fois juste au moment où le timer s'éxécute. Pour le script, il ne fera pas la différence avec un appui long.
Pour éviter ce travers, il fadrait mettre un timer très court et compter le nombre de fois où on passe dedans. Et ceci pour chaque joueur. Pas commode et gourmand en ressource.
En fait il est très facile de la faire avec OnPlayerKeyStateChange :
Lorsque le joueur appuie sur la touche en question, on mémorise le moment où il l'a fait (avec la fonction gettime sous Linux ou mieux, GetTickCount sous Windows).
Pour ce faire, on test le paramètre newkeys pour savoir si c'est la bonne touche (on positionne un flag par exemple).
Lorsque le joueur relache la touche, OnPlayerKeyStateChange est appelé une nouvelle fois.
Il suffit alors de calculer la durée entre les deux appels à OnPlayerKeyStateChange et le tour est joué (on peut faire des tests sur newkeys pour voir si la touche a bien été relachée).
NB : La fonction GetTickCount (qui renvoie le nombre de miliseconde écoulées depuis le démarrage de la machine) est très pratique pour faire ce genre de chose et elle est très précise. Par contre, elle n'existe pas sous Linux. Mais on peut trouver des plugins qui émulent cette fonction.
++
Syg
-
Heu le gettime marche aussi sous windows :p Je me suis servis pour mettre l'heure sur mon serveur ;)
-
Ok merci, je comprends à peu près et en effet, si le GetPlayerKeys est gourmand et (comme je le pensais ^^ : Eh oui ça m'arrive de penser XD) si on ne définit pas un temps court, il ne fait pas la différence entre un appui long et deux appuis courts aux bons moments, c'est mieux d'utiliser la callback OnPlayerKeyStateChange comme tu le dis Syg.
Je vois donc comment vérifier si newkeys est la bonne touche (avec une condition si je ne m'abuse : if(newkeys == KEY_FIRE){ par exemple) par contre je ne vois pas comment rappeller la callback quand la touche est relachée et je n'ai jamais utilisé GetTickCount donc je ne sais pas comment il fonctionne.
Pourrais-tu me détailler cette méthode Syg s'il te plait ?
Merci d'avance !
Jens84
-
Tout d'abord, tu n'as pas besoin de rappeler la callback OnPlayerKeyStateChange, le moteur de SAMP va le faire tout seul pour toi, à chaque appui ou relachement d'une touche.
Ensuite, je n'ai jamais dit que gettime n'existait pas sous Windows, ce que je voulais dire c'est que gettime donne heures, minutes et secondes alors que GetTickCount donne des milisecondes (donc 1000 fois plus précis).
Pour le test sur newkeys, il faut passer par un masque, pas par une comparaison à l'égalité car newkeys peut contenir plusieurs codes touche à la fois.
if (newkeys & KEY_FIRE)
Pour la méthode, c'est facile, lors de l'appuie sur la touche voulue tu stockes l'instant à laquelle la touche est appuyée. Lors du relachement de la touche, tu fais la différence entre l'instant présent et l'instant stocké avant. Ceci te donne la durée d'appui sur la touche. Il ne reste plus qu'à comparer avec la durée voulue.
Pour n'importe quel serveur :
new Temps[MAX_PLAYERS];
public OnPlayerKeyStateChange (playerid, newkeys, oldkeys)
{
new H, M, S;
gettime (H, M, S);
/* On vient d'appuyer sur la touche KEY_FIRE */
if (newkeys & KEY_FIRE)
{
/* On stocke l'instant d'appui sur la touche */
Temps[playerid] = H*3600 + M*60 + S;
}
/* On vient de relacher la touche KEY_FIRE */
else if (oldkeys & KEY_FIRE)
{
/* On stocke l'instant de relachement de la touche */
Temps2 = H*3600 + M*60 + S;
/* Si appui assez long (supérieur à 5 secondes) */
if (Temps2-Temps[playerid] > 5)
{
/* Tu fais ce que tu as à faire */
}
}
}
Pour un serveur sous Windows (seulement) :
new Temps[MAX_PLAYERS];
public OnPlayerKeyStateChange (playerid, newkeys, oldkeys)
{
/* On vient d'appuyer sur la touche KEY_FIRE */
if (newkeys & KEY_FIRE)
{
/* On stocke l'instant d'appui sur la touche */
Temps[playerid] = GetTickCount ();
}
/* On vient de relacher la touche KEY_FIRE */
else if (oldkeys & KEY_FIRE)
{
/* On stocke l'instant de relachement de la touche */
new Temps2 = GetTickCount ();
/* Si appui assez long (supérieur à 5 secondes) */
if (Temps2-Temps[playerid] > 5000)
{
/* Tu fais ce que tu as à faire */
}
}
}
Attention, pour la première version (sans GetTickCount), il faut gérer le passage à minuit si on veut faire les chose correctement. Effectivement, si le joueur appuie sur la touche à 23:59:58 et la relâche à 00:00:04, il se sera passé plus de 5 secondes mais le script ne le verra pas car la différence entre les deux temps sera négative vu qu'on repasse à 0.
23:59:58 -> 23*3600+59*60+58 = 86398 (Temps[playerid] dans le script)
00:00:04 -> 00*3600+00*60+04 = 4 (Temps2 dans le script)
4 - 86398 = -86394 (qui n'est bien évidement pas supérieur à 5).
Mais bon, la gestion du passage à minuit n'est pas indispensable.
++
Syg
-
Salut,
et j'ajouterais un cours sur le symbole '&' de notre maitre à tous Syg:
http://www.gtaonline.fr/forums/index.php/topic,3916.0.html (http://www.gtaonline.fr/forums/index.php/topic,3916.0.html)
++Sim++
-
Merci beaucoup Syg, on remarque un vrai professionnel en la matière, et c'est bien ton cas !
Il me semblait bien avoir dit une conner** avec mon if(newkeys == KEY_FIRE){ car j'utilise assez OnPlayerKeyStateChange et je connais donc la bonne formule XD.
Ben en tout cas merci beaucoup, je testerai ça ce soir !
A bientôt !
Jens84
-
A chaque fois que syg explique je reste sur le cul xD C'est impressionnant on vois bien que c'est ton domaine a 100% ;)