Cette section vous explique comment déterminer et personnaliser les équipes et les classes pour les joueurs.
Appareils utilisés :
Inventaire et paramètres d'équipe
Utilisez les appareils Inventaire et paramètres d'équipe pour définir les noms et les couleurs des équipes en vue de les afficher dans le tableau des scores.
Placez un appareil par équipe dans une zone que les joueurs ne voient pas. Pour configurer l'équipe des accessoires, définissez les options utilisateur en fonction du tableau ci-dessous.
| Option | Valeur | Explication | |
|---|---|---|---|
| Nom de l'équipe | Accessoires | Définit une chaîne de texte qui sera utilisée pour identifier cette équipe dans le tableau des scores et dans l'ATH. | |
| Couleur de l'équipe | Bleu ciel | Attribue à l'équipe sélectionnée une couleur utilisée dans le tableau des scores, dans l'ATH et sur certains appareils. | |
| Équipe | Index d'équipe : 1 | Définit à quelle équipe les paramètres de cet appareil s'appliquent. |
Pour configurer l'équipe des chasseurs, définissez les options utilisateur de l'autre appareil pour qu'elles correspondent au tableau ci-dessous.
| Option | Valeur | Explication | |
|---|---|---|---|
| Nom de l'équipe | Chasseurs | Définit une chaîne de texte qui sera utilisée pour identifier cette équipe dans le tableau des scores et dans l'ATH. | |
| Couleur de l'équipe | Orange | Attribue à l'équipe sélectionnée une couleur utilisée dans le tableau des scores, dans l'ATH et sur certains appareils. | |
| Équipe | Index d'équipe : 2 | Définit à quelle équipe les paramètres de cet appareil s'appliquent. |
Concepteur de classe
Utilisez un concepteur de classe pour modifier les équipes que vous venez de créer.
Placez deux concepteurs de classe, un pour chaque équipe, dans une zone que les joueurs ne voient pas. Pour personnaliser l'équipe des accessoires, définissez les options utilisateur en fonction du tableau ci-dessous.
| Option | Valeur | Explication |
|---|---|---|
| Nom de la classe | Accessoire | Détermine le nom de cette classe. |
| Description de la classe | Cachez-vous des chasseurs et survivez. | Définit la description de cette classe. |
| Identificateur de classe | Emplacement de classe : 1 | Définit l'identificateur unique de cette classe. |
| PV max | 1 | Détermine le nombre maximum de PV que les joueurs peuvent atteindre au cours du jeu. Un seul impact suffit pour éliminer les accessoires. |
| Liste des objets | Transformaccessoire | Définit la liste des objets de cette classe. |
| Équiper les objets remis | Premier objet | Détermine l'objet de la liste qui sera équipé. |
Pour personnaliser l'équipe des chasseurs, définissez les options utilisateur de l'autre appareil pour qu'elles correspondent au tableau ci-dessous.
| Option | Valeur | Explication |
|---|---|---|
| Nom de la classe | Chasseur | Détermine le nom de cette classe. |
| Description de la classe | Cherchez les accessoires et éliminez-les. | Définit la description de cette classe. |
| Identificateur de classe | Emplacement de classe : 2 | Définit l'identificateur unique de cette classe. |
| Liste des objets | Pistolampe | Définit la liste des objets de cette classe. |
| Équiper les objets remis | Premier objet | Détermine l'objet de la liste qui sera équipé. |
Sélecteur de classe
Associez le concepteur de classe au sélecteur de classe pour gérer les classes et les équipes personnalisées que vous créez.
En plus de Verse, les paramètres de cet appareil permettent de transférer les joueurs de l'emplacement de classe 1 vers l'emplacement de classe 2 lorsqu'ils réapparaissent.
Placez deux sélecteurs de classe, un pour chaque équipe, dans une zone que les joueurs ne voient pas. Pour gérer l'équipe des accessoires, utilisez les paramètres du tableau ci-dessous pour configurer les options utilisateur de cet appareil.
| Option | Valeur | Explication |
|---|---|---|
| Classe vers laquelle changer | Emplacement de classe : 1 | Définit la classe vers laquelle le joueur doit changer. |
| Visible pendant le jeu | Désactivé | Cet appareil n'est pas visible pendant le jeu. |
| Son d'entrée dans la zone | Désactivé | Définit si le sélecteur de classe doit jouer un effet sonore quand un joueur entre dans la zone. |
| Équipe de transfert | Index d'équipe : 1 | Définit l'équipe vers laquelle est transféré le joueur. |
| Retirer les objets au changement de classe | Activé | Définit si les objets doivent être retirés de l'inventaire du joueur au moment du changement. |
| Volume visible pendant le jeu | Désactivé | Définit si le volume de l'appareil est visible pendant le jeu. |
| Afficher les effets visuels à l'activation | Désactivé | Définit si l'appareil doit créer un effet visuel lors du changement de classe ou d'équipe d'un joueur. |
Pour gérer l'équipe des chasseurs, utilisez les paramètres du tableau ci-dessous pour configurer les options utilisateur de cet appareil.
| Option | Valeur | Explication |
|---|---|---|
| Classe vers laquelle changer | Emplacement de classe : 2 | Définit la classe vers laquelle le joueur doit changer. |
| Équipe de transfert | Index d'équipe : 2 | Définit l'équipe vers laquelle est transféré le joueur. |
Créer une fonctionnalité d'équipe avec Verse
Ce jeu Chasse aux accessoires comporte deux équipes : les chasseurs et les accessoires. Pour que le jeu fonctionne, il faut parfois que vous puissiez réaliser les mêmes actions pour les deux équipes. Par exemple :
-
ajouter des joueurs à une équipe ;
-
supprimer des joueurs d'une équipe ;
-
afficher des informations aux joueurs concernant leur équipe.
Pour créer cette fonctionnalité pour les deux équipes sans dupliquer de code, vous allez créer une classe avec le spécificateur <abstract>. Les classes dotées du spécificateur abstract sont conçues pour disposer de certaines fonctionnalités dont leurs sous-classes héritent et sur lesquelles elles s'appuient. Vous commencerez par créer une classe abstract appelée base_team et lui donner la fonctionnalité que l'équipe des accessoires et celle des chasseurs partageront.
Ce tutoriel comprend des extraits de code Verse qui vous expliquent comment exécuter les mécaniques de jeu nécessaires dans ce jeu. Suivez les étapes ci-dessous et copiez le script complet à l'étape 6 de ce tutoriel.
Créez un nouveau fichier Verse dans votre projet appelé base_team.verse. Il ne s'agit pas d'un appareil Verse ; vous pouvez donc le créer en tant que fichier Verse vide.
using { /Fortnite.com/Characters }
using { /Fortnite.com/Devices }
using { /Fortnite.com/UI }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /UnrealEngine.com/Temporary/UI }
using { /Verse.org/Colors }
using { /Verse.org/Simulation }
log_team := class(log_channel){}
# Cette classe définit les appareils nécessaires aux diverses équipes du jeu.
# Cette classe abstraite n'est pas utilisable seule. Une autre classe doit en hériter.
base_team := class<abstract>:
Logger:log = log{Channel:=log_team}
@editable # Permet d'affecter un joueur à l'équipe.
ClassSelector:class_and_team_selector_device = class_and_team_selector_device{}
@editable # Permet d'attribuer un score aux agents de l'équipe.
ScoreManager:score_manager_device = score_manager_device{}
@editable # Permet d'afficher le titre d'assignation de l'équipe.
TeamTitle:hud_message_device = hud_message_device{}
@editable # Permet d'afficher la description d'assignation de l'équipe.
TeamDescription:hud_message_device = hud_message_device{}
@editable # Permet de s'abonner aux événements d'élimination des membres de l'équipe (équipe des accessoires) ou des ennemis (équipe des chasseurs).
TeamManager:team_settings_and_inventory_device = team_settings_and_inventory_device{}
# Voici une matrice des agents de l'équipe.
var TeamAgents<private>:[]agent = array{}
# Cet événement est déclenché lorsque la matrice TeamAgents est vide (signal de fin de manche).
TeamEmptyEvent:event() = event(){}
# Renvoyer la matrice TeamAgents actuelle.
# Cela est nécessaire en raison du caractère privé de la matrice TeamAgents, qui fait que les autres classes ne peuvent pas y accéder directement.
GetAgents()<decides><transacts>:[]agent =
TeamAgents
# Renvoyer la taille de la matrice TeamAgents
# Une fonction est nécessaire ici en raison du caractère privé de la matrice TeamAgents, qui fait que les autres classes ne peuvent pas y accéder directement.
Count()<transacts>:int =
TeamAgents.Length
# Renvoie un index dans la matrice TeamAgents d'un agent, sinon échoue.
FindOnTeam(Agent:agent)<decides><transacts>: int =
Index := TeamAgents.Find[Agent]
# Attribuer l'agent à l'équipe et notifier le joueur.
InitializeAgent(Agent:agent):void =
AddAgentToTeam(Agent)
ClassSelector.ChangeTeamAndClass(Agent)
DisplayTeamInformation(Agent)
# Ajouter un agent à TeamAgents.
AddAgentToTeam(AgentToAdd:agent):void =
if (not FindOnTeam[AgentToAdd]):
Logger.Print("Adding agent to team.")
set TeamAgents += array{AgentToAdd}
# Activer les appareils de message d'ATH pour informer le joueur de l'équipe dont il fait partie
DisplayTeamInformation(Agent:agent):void =
TeamTitle.Show(Agent)
TeamDescription.Show(Agent)
# Lorsqu'un agent quitte la partie, le retirer de la matrice TeamAgents et vérifier si la manche est terminée.
EliminateAgent(Agent:agent)<suspends>:void =
Sleep(0.0) # Retarder 1 tick de jeu pour s'assurer de la réapparition du joueur avant de continuer.
RemoveAgentFromTeam(Agent)
# Retirer un agent de TeamAgents.
# Si l'agent retiré était le dernier, déclencher TeamEmptyEvent.
RemoveAgentFromTeam(AgentToRemove:agent):void =
set TeamAgents = TeamAgents.RemoveAllElements(AgentToRemove)
Logger.Print("{Count()} agent(s) on team remaining.")
if (Count() < 1):
Logger.Print("No agents on team remaining. Ending the round.")
TeamEmptyEvent.Signal()
Maintenant que vous disposez de cette classe, vous pouvez créer les classes de l'équipe des accessoires et de l'équipe des chasseurs. Le fait que chacune d'elles hérite de base_team présente les avantages suivants :
-
Le code pour implémenter chaque équipe est beaucoup plus court, car les fonctions et données communes des équipes sont déjà définies dans
base_team. -
Il est plus facile de comprendre le code spécifique aux équipes des accessoires et des chasseurs, car il est contenu dans les classes propres à chaque équipe au lieu d'être mélangé au code commun.
-
Il est beaucoup plus facile d'ajouter d'autres équipes au mode de jeu. Toute nouvelle équipe hérite de
base_team, et le code qui différencie la nouvelle équipe se trouve dans sa propre classe.
N'oubliez pas que vous ne pouvez pas créer une instance de classe avec le spécificateur <abstract>. Vous devez créer une classe qui hérite de la classe abstract et l'instancier.
Équipe des chasseurs
Tout d'abord, créez la classe pour l'équipe des chasseurs. Créez un nouveau fichier Verse dans votre projet appelé hunter_team.verse. Il ne s'agit pas d'un appareil Verse ; vous pouvez donc le créer en tant que fichier Verse vide.
Déclarez une classe nommée hunter_team. Elle doit être <concrete> et hériter également de base_team.
hunter_team := class<concrete>(base_team):
Rendre une classe <concrete> signifie que tous ses champs doivent posséder une valeur par défaut. Pour en savoir plus, consultez la rubrique Spécificateurs et attributs.
Vous trouverez ci-dessous le code complet du script hunter_team.verse.
La classe hunter_team possède deux fonctions portant le même nom que les fonctions de la classe base_team. Cela est autorisé, car elles ont toutes les deux le spécificateur <override>. Cela signifie que lorsque ces fonctions sont appelées sur une instance de hunter_team, c'est la version de la classe hunter_team qui est utilisée.
Par exemple, dans le code suivant, la version d'InitializeAgent() définie dans hunter_team est utilisée, car elle remplace la fonction du même nom dans base_team. Cela est à comparer à l'appel de Count(), qui utilise la version définie dans base_team en raison de l'absence de fonction de remplacement.
HunterTeam:hunter_team = hunter_team{}
# Utilise la fonction de hunter_team
HunterTeam.InitializeAgent(StartingHunterAgent)
# Utilise la fonction de base_team
HunterTeam.Count()
Les deux fonctions remplacées utilisent également (super:). Cela leur permet d'appeler la version des fonctions définies dans base_team, car base_team est la super-classe de hunter_team. Dans le cas d'InitializeAgent() et d'EliminateAgent(), tous deux utilisent Logger.Print() pour afficher du texte dans le journal. Ils appellent ensuite leurs fonctions respectives à partir de base_team. En d'autres termes, les fonctions opèrent exactement de la même manière que les versions de base_team, à l'exception des appels à Logger.Print().
Consultez la rubrique Sous-classe pour en savoir plus sur <override> et (super:)
Équipe des accessoires
Créez maintenant la classe pour l'équipe des accessoires. Créez un nouveau fichier Verse dans votre projet appelé prop_team.verse. Il ne s'agit pas d'un appareil Verse ; vous pouvez donc le créer en tant que fichier Verse vide.
Vous devez gérer des éléments supplémentaires pour les membres de l'équipe des accessoires. Ceux-ci ont des effets de battement de cœur qui doivent être activés et désactivés en fonction d'un chronomètre et de la distance qu'ils parcourent. Ils doivent également être transférés dans l'équipe des chasseurs lorsqu'ils sont éliminés.
Pour gérer les membres de l'équipe des accessoires, utilisez la méthode RunPropGameLoop(). Vous pouvez considérer cette méthode comme le gestionnaire de l'ensemble du parcours d'un accessoire dans le jeu. Cette méthode s'applique à tous les membres de l'équipe des accessoires, entre le moment où ils apparaissent et le moment où ils sont éliminés ou quittent le jeu.
# Si l'agent d'accessoire s'arrête de bouger, utiliser race pour voir si l'agent d'accessoire se déplace au-delà du paramètre MinimumMoveDistance, si le chronomètre de battement de cœur se termine, ou si l'agent d'accessoire est éliminé.
RunPropGameLoop(PropAgent:agent)<suspends>:void =
Logger.Print("Starting prop agent game loop.")
# Mettre le comportement de l'accessoire en boucle infinie jusqu'à ce que l'agent d'accessoire soit éliminé ou que le joueur quitte la session.
race:
PropAgent.AwaitNoLongerAProp()
loop:
# Attendre que l'agent d'accessoire se déplace à une distance inférieure à la distance minimale, puis avancer.
PropAgent.AwaitStopMoving(MinimumMoveDistance)
# Compte à rebours jusqu'au battement de cœur en attendant que l'agent d'accessoire dépasse la distance minimale, puis déclenchement indéfini du battement de cœur.
race:
PropAgent.AwaitStartMoving(MinimumMoveDistance)
block:
CountdownTimer(PropAgent)
PropAgent.StartHeartbeat()
Sleep(0.0) # Une fois la fonction race terminée (déplacement de l'agent d'accessoire), relancer la boucle.
RunPropGameLoop() dispose d'un paramètre : PropAgent. Il s'agit d'une constante qui représente un joueur de l'équipe des accessoires. Il possède également le spécificateur <suspends>, ce qui signifie qu'il met du temps à se terminer. En l'occurrence, il ne se termine pas tant que le PropAgent transmis ne fait plus partie de l'équipe des accessoires.
L'ensemble de la fonctionnalité de cette méthode est contenu dans une expression race. En d'autres termes, la méthode ne prend pas fin tant que l'une des expressions au sein de la course (race) n'est pas terminée. Ces expressions sont les suivantes :
-
PropAgent.AwaitNoLongerAProp() -
loop
L'expression loop de cette course ne s'arrête jamais. Elle est volontairement infinie. Cela signifie qu'AwaitNoLongerAProp() est la méthode qui gagne toujours la course et met fin à la méthode. Utiliser la course de cette manière revient à demander à votre programme d'exécuter un code en boucle jusqu'à ce qu'un événement se produise. Consultez la rubrique L'expression race pour en savoir plus sur cette expression puissante.
Avec ce code, AwaitNoLongerAProp() gagne la course.
# Mettre en boucle jusqu'à ce que l'agent d'accessoire ne fasse plus partie de la matrice PropAgents. Le retrait a lieu si l'agent d'accessoire est éliminé et transformé en chasseur ou si le joueur quitte la session.
(PropAgent:agent).AwaitNoLongerAProp()<suspends>:void =
loop:
if (not FindOnTeam[PropAgent]):
Logger.Print("Cancelling prop agent behavior.")
break
Sleep(0.0) # Passer au tick de jeu suivant.
Cette méthode vérifie constamment si PropAgent fait partie de l'équipe des accessoires. Elle commence par une boucle qui s'exécute jusqu'à ce que not FindOnTeam[PropAgent] réussisse, puis s'interrompt, mettant ainsi fin à la méthode. Consultez la rubrique Les expressions loop et break pour en savoir plus.
FindOnTeam[] est une fonction faillible déclarée dans base_team. Elle réussit si PropAgent est trouvé dans l'équipe des accessoires. Vous devez toutefois utiliser l'opérateur not, car vous ne souhaitez interrompre la boucle que si PropAgent est introuvable dans l'équipe des accessoires. Consultez la rubrique Opérateurs pour en savoir plus sur not.
Enfin, vous devez ajouter Sleep(0.0) à la fin de la boucle. Vous vous assurez ainsi que la boucle s'exécute une fois, puis passe à la mise à jour de la simulation suivante. Vous n'avez pas besoin d'exécuter cette vérification plus souvent, c'est pourquoi Sleep(0.0) est ajouté pour améliorer les performances. Consultez la page Référence API de Verse pour en savoir plus sur la fonction Sleep.
Maintenant que vous savez comment fonctionne AwaitNoLongerAProp(), vous pouvez écrire la boucle infinie qui l'accompagne dans RunPropGameLoop().