C_far+ 442 Signaler ce message Posté(e) 5 décembre 2015 (modifié) Créer un décompte J'crée ce tutoriel car ça fait plusieurs fois qu'on me demande comment créer un décompte. Je vais essayer d'être le plus compréhensif possible, donc n'hésitez pas à me faire une remarque si vous ne comprenez la formulation d'une phrase. Il n'y a rien de bien compliqué je vous rassure.[/centre] Niveau de difficulté : Débutant Requis : Une connaissance des bases du Pawn De la logiqueFonctionnement : Notre décompte se lancera lorsque le joueur se connectera, il devra attendre 10 secondes pour spawn. Durant ces 10 secondes nous lui afficherons qu'il spawnera dans X secondes, ce nombre changera toutes les secondes. A la fin de ce décompte, nous ferons spawn le joueur et nous lui afficherons qu'il a spawn.Théorie et Pratique : Nous allons d'abord déclarer 2 tableaux : Un qui stockera le nombre de secondes par joueur (imaginons qu'il y ait plusieurs joueurs qui spawnent en 10 secondes) Un qui stockera l'id du timer que nous utiliserons pour notre décompte new temps_Decompte[MAX_PLAYERS char], // J'ai déclaré un tableau char, car nous stockerons un entier qui ne sera pas supérieur à 10. timer_Decompte[MAX_PLAYERS]; Voilà! On va maitenant s'occuper du code lorsque le joueur se connecte. Vous pensez que je vais utiliser OnPlayerConnect, mais je vais volontairement utiliser OnPlayerRequestClass pour cacher le bouton spawn. public OnPlayerRequestClass(playerid, classid) { return 1; } Voici notre callback. Pour "cacher" ce fameux bouton spawn, je vais utiliser la fonction TogglePlayerSpectating. En utilisant cette fonction dans notre callback, cela cachera obligatoirement ce bouton spawn hé oui (essayez!). public OnPlayerRequestClass(playerid, classid) { TogglePlayerSpectating(playerid, true); return 1; } Maintenant on va pouvoir s’intéresser à la partie affichage du texte et lancement du timer. Nous utiliserons les fonctions : GameTextForPlayer pour afficher le texte sur l'écran du joueur. SetTimerEx pour lancer un timer avec en paramètre l'id joueur. Je vous invite à consulter le wiki des fonctions, je ne vais pas expliquer leur fonctionnement. public OnPlayerRequestClass(playerid, classid) { TogglePlayerSpectating(playerid, true); GameTextForPlayer(playerid, "Vous allez spawn dans 10 secondes.", 1100, 6); // On affiche au joueur qu'il spawnera dans 10 secondes timer_Decompte[playerid] = SetTimerEx("DecompteJoueur", 1000, true, "i", playerid); // On lance le timer avec une intervalle d'une 1 seconde. On précise que nous souhaitons l'id du joueur en paramètre. On récupère son id qu'on stocke dans notre variable. return 1; } Il ne nous manque qu'une chose dans notre callback ! Attribuer le nombre de secondes de notre décompte à notre tableau temps_Decompte public OnPlayerRequestClass(playerid, classid) { TogglePlayerSpectating(playerid, true); GameTextForPlayer(playerid, "Vous allez spawn dans 10 secondes.", 1100, 6); timer_Decompte[playerid] = SetTimerEx("DecompteJoueur", 1000, true, "i", playerid); temps_Decompte{playerid} = 10; // Nous utilisons des accolades au lieu de crochets autour de playerid, car c'est un tableau char (packed). return 1; } La première partie est faite. Attaquons maintenant le code qui sera exécuté dans notre timer. forward DecompteJoueur(playerid); public DecompteJoueur(playerid) { return 1; } Premièrement nous allons décrémenter notre variable qui stocke le nombre de secondes, car nous voulons évidemment un entier inférieur à celui d'avant dans notre décompte :')). forward DecompteJoueur(playerid); public DecompteJoueur(playerid) { temps_Decompte{playerid}--; return 1; } On va maintenant ré-utiliser notre fonction GameTextForPlayer pour afficher le texte. Mais étant donné que notre texte comportera le nombre de secondes restantes, qui seront différentes chaque seconde, on va devoir formater notre chaîne de caractères. Pour ça, on utilise format. forward DecompteJoueur(playerid); public DecompteJoueur(playerid) { temps_Decompte{playerid}--; static str[34]; // J'ai indexé mon tableau à 34, car notre texte ne comporte pas plus de 33 caractères + le nullbyte format(str, sizeof(str), "Vous allez spawn dans %d secondes.", temps_Decompte{playerid}); return GameTextForPlayer(playerid, str, 1100, 6); } Il va maintenant falloir arrêter notre timer, lui dire qu'à 0 seconde il s'arrête, qu'il fasse spawn notre joueur et qu'il affiche un message au joueur comme quoi celui-ci vient de spawn! Outch ça en fait des actions! Non j'déconne sur 4 lignes c'est fait. Nous utiliserons : TogglePlayerSpectating pour désactiver le mode spectateur du joueur. En le désactivant, le joueur spawnera. GameTextForPlayer pour afficher le texte. KillTimer pour arrêter notre timer. forward DecompteJoueur(playerid); public DecompteJoueur(playerid) { temps_Decompte{playerid}--; if(temps_Decompte{playerid} == 0) // Si le nombre de secondes est à 0 { TogglePlayerSpectating(playerid, false); // On désactive le mode spectateur du joueur et le fera spawn GameTextForPlayer(playerid, "Vous venez de spawn.", 2000, 6); // On affiche au joueur qu'il a spawn KillTimer(timer_Decompte[playerid]); // On arrête le timer. return 1; // On retourne pour sortir de notre timer } static str[34]; format(str, sizeof(str), "Vous allez spawn dans %d secondes.", temps_Decompte{playerid}); return GameTextForPlayer(playerid, str, 1100, 6); } Modifié 10 juillet 2016 par C_far Partager ce message Lien à poster Partager sur d’autres sites
Hodor 2 Signaler ce message Posté(e) 9 juillet 2016 (modifié) En reprenant ton exemple, on peut tout regrouper en une seule fonction et ainsi s'épargner la lourdeur de voir trainer des variables globales ici ou ailleurs. Exemple : #include <a_samp> // pas de new globaux. public OnPlayerRequestClass(playerid, classid) { TogglePlayerSpectating(playerid, true); GameTextForPlayer(playerid, "Vous allez spawn dans 10 secondes.", 1100, 6); SetPlayerSpawnDelay(playerid, 10); return 1; } forward SetPlayerSpawnDelay(playerid, seconds); public SetPlayerSpawnDelay(playerid, seconds) { static timer[MAX_PLAYERS char]; static timer_tag; if(seconds != -1) // pour initialiser le timer. { timer{playerid} = seconds; return timer_tag = SetTimerEx("SetPlayerSpawnDelay", 1000, true, "ii", playerid, -1); } if(timer{playerid} == 0) // le reste comme dans ton exemple. { KillTimer(timer_tag); return TogglePlayerSpectating(playerid, false); } new string[34]; format(string,sizeof(string),"Vous allez spawn dans %d", timer{playerid}); timer{playerid}--; GameTextForPlayer(playerid, string, 1100, 6); return 1; } Ca rajoute un if et un parametre dans la fonction, du coup un calcul supplémentaire à chaque appel. Est ce que ca en vaut la peine ? Dans la mesure ou on a pas à éparpiller son code, définir des variables globales, les initialiser dans une autre callback etc, c'est tout benef, surtout avec ce langage ou t'es assez limité. Et pour une fois on peut se vanter d'avoir utilisé toutes les propriétés utiles des static. Modifié 9 juillet 2016 par Hodor toggleplayerspec dans la fonction pas controlable. rectifié Partager ce message Lien à poster Partager sur d’autres sites
C_far+ 442 Signaler ce message Posté(e) 10 juillet 2016 (modifié) @Hodor ce tutoriel est dédié aux débutants et était le premier que j'ai rédigé sur le forum officiel, il est évident que je n'allais pas mentionner de parties compliquées. Maintenant dans ton exemple, la variable statique peut être un bon moyen d'éviter la variable globale, mais y voyons une optimisation ? Au contraire, tout ce qui change c'est la portée des variables, car une variable statique ou globale sera située obligatoirement dans le DATA, donc sera initialisé dans l'amx et la valeur sera stockée tout le temps du programme. Tout ce qu'il y a de bon dans ton cas, c'est la portée. Maintenant, l'intérêt d'avoir ce genre de variables en global ? Pouvoir y accéder depuis d'autres fonctions, car là c'est un exemple bidon que j'ai posté, mais l'utilité d'un décompte peut être poussé à bien plus intéressant sur de bons systèmes. Il y a 10 heures, Hodor a dit : Ca rajoute un if et un parametre dans la fonction, du coup un calcul supplémentaire à chaque appel. Une comparaison supplémentaire à chaque appel, c'est déjà beaucoup trop. Sans parler d'un paramètre supplémentaire, qui surplombe donc le FRAME inutilement. Conclusion : Ce que tu as fait est bien, mais n'est pas optimisé. Edit : D'ailleurs ton code ne permettra de ne faire tourner qu'un décompte à la fois, sans quoi si un deuxième est lancé pendant le premier, à la fin de celui-ci le second décompte s'arrêtera, mais le premier continuera de tourner. Modifié 10 juillet 2016 par C_far Partager ce message Lien à poster Partager sur d’autres sites
Hodor 2 Signaler ce message Posté(e) 10 juillet 2016 Ah oui j'ai mal copié ton exemple j'ai pas mis timer_tag[max_players], erreur d'inattention, c'est vrai que c'est con sinon. Après, je n'ai pas dit que c'était le code le plus rapide évidemment ca ne l'est pas du coup, et si tu comptes réutiliser ta variable globale timer_decompte etc, ca va pas le faire c'est sur, mais sinon ca reste valable dans le sens ou on ne cherche pas toujours à avoir un code le plus rapide possible au détriment d'autres facteurs. Merci pour ta rep C_ ! Partager ce message Lien à poster Partager sur d’autres sites
Audrey 0 Signaler ce message Posté(e) 31 juillet 2017 Salut j'ai un soucis, lors de la fin de ton décompte, il spawn, mais je suis kick du serveur. Ma connexion a été fermé... Une réponse ? Un conseil ? Partager ce message Lien à poster Partager sur d’autres sites
C_far+ 442 Signaler ce message Posté(e) 31 juillet 2017 (modifié) Pfiou j'en avais oublié ce tutoriel horrible 13 minutes ago, Audrey said: Salut j'ai un soucis, lors de la fin de ton décompte, il spawn, mais je suis kick du serveur. Ma connexion a été fermé... Une réponse ? Un conseil ? Le code ? Modifié 31 juillet 2017 par C_far Partager ce message Lien à poster Partager sur d’autres sites
Audrey 0 Signaler ce message Posté(e) 31 juillet 2017 J'ai pris exactement le tient, mais voici: public DecompteJoueur(playerid) { temps_Decompte{playerid}--; if(temps_Decompte{playerid} == 0) // Si le nombre de secondes est à 0 { TogglePlayerSpectating(playerid, false); // On désactive le mode spectateur du joueur et le fera spawn GameTextForPlayer(playerid, "Vous venez de spawn.", 2000, 6); // On affiche au joueur qu'il a spawn KillTimer(timer_Decompte[playerid]); // On arrête le timer. return 1; // On retourne pour sortir de notre timer } static str[148]; format(str, sizeof(str), "Chargement du jeu en cours... Attendez %d secondes.", temps_Decompte{playerid}); return GameTextForPlayer(playerid, str, 1100, 6); } public OnPlayerRequestClass(playerid, classid) // -1442.4795,2593.5142,55.8359 { TogglePlayerSpectating(playerid, true); GameTextForPlayer(playerid, "Vous allez spawn dans 10 secondes.", 1100, 6); // On affiche au joueur qu'il spawnera dans 10 secondes timer_Decompte[playerid] = SetTimerEx("DecompteJoueur", 1000, true, "i", playerid); // On lance le timer avec une intervalle d'une 1 seconde. On précise que nous souhaitons l'id du joueur en paramètre. On récupère son id qu'on stocke dans notre variable. temps_Decompte{playerid} = 10; // Nous utilisons des accolades au lieu de crochets autour de playerid, car c'est un tableau char (packed). /*SetPlayerPos(playerid,199.0846,-150.0331,1.5781); SetPlayerCameraPos(playerid, 199.2307,-143.8328,1.5781); SetPlayerCameraLookAt(playerid, 199.0846,-150.0331,1.5781); SetPlayerFacingAngle(playerid,359.1443);*/ return 1; } Partager ce message Lien à poster Partager sur d’autres sites
Maceo7 1 Signaler ce message Posté(e) 31 juillet 2017 Utilise http://wiki.sa-mp.com/wiki/SetSpawnInfo avant d'off le Spectating . Partager ce message Lien à poster Partager sur d’autres sites