Dans cette étape du tutoriel
Le gestionnaire de score assure le suivi et l'affichage des éléments suivants :
Nombre total de points : représente le nombre total de points marqués par le joueur dans le jeu.
Points en attente : représente les points que le joueur a accumulés jusqu'à maintenant pour la série de collectes actuelle.
Niveau de collecte : représente le niveau de collecte actuel.
Créer l'interface utilisateur
Procédez comme suit pour créer l’interface utilisateur du gestionnaire de score dans Verse :
Créez un nouveau fichier Verse vide et nommez-le score_manager.verse.
Créez une nouvelle classe nommée
score_manageret ajoutez-y les champs suivants :Un
agentfacultatif nomméMaybePlayerpour stocker une référence au joueur.MaybePlayer<internal> : ?agent = falseUne interface
player_uifacultative nomméeMaybePlayerUIpour stocker une référence à l'interface utilisateur du joueur.MaybePlayerUI<internal> : ?player_ui = falseUn appareil
score_manager_devicepour stocker une référence à l'appareil Gestionnaire de score avec lequel cette classe est construite. Notez que cette référence n'est pas modifiable, car elle doit être reliée à l'appareilgame_coordinator_devicecréé avec Verse.ScoreManagerDevice<internal> : score_manager_device = score_manager_device{}Une variable entière nommée
TotalGameScorequi représente tous les points que le joueur a marqués dans le jeu en général.var TotalGameScore<private> : int = 0Une variable entière nommée
PendingScorequi représente les points que le joueur a actuellement accumulés pour cette série de collectes.var PendingScore<private> : int = 0Une variable entière nommée
PickupLevelqui représente le niveau de collecte actuel.var PickupLevel<private> : int = 0
Votre définition de classe score_manager doit maintenant être similaire à ce qui suit :
score_manager := class: MaybePlayer<internal> : ?agent = false MaybePlayerUI<internal> : ?player_ui = false ScoreManagerDevice<internal> : score_manager_device = score_manager_device{} var TotalGameScore<private> : int = 0 var PendingScore<private> : int = 0 var PickupLevel<private> : int = 0Créez l'interface utilisateur lors de la création initiale de la classe. Pour ce faire, ajoutez à la définition de classe une expression
blockqui s'exécutera chaque fois que vous créerez une instance de la classe. Ajoutez les variables suivantes pour générer l'IU :Une variable
canvasnomméeCanvasavec le spécificateurinternalpour stocker le widget de zone de dessin personnalisé.var Canvas<internal> : canvas = canvas{}Un
bloc de textenomméTotalGameScoreWidgetavec le spécificateurinternal, pour stocker le widget de texte et afficher tous les points que le joueur a marqués dans le jeu en général, tel que représenté par la variableTotalGameScore. Définissez le texte par défaut du bloc de texte sur la couleur blanche.TotalGameScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White}Un
bloc de textenomméPendingScoreWidgetavec le spécificateurinternal, pour stocker le widget de texte et afficher les points que le joueur a accumulés jusqu'à présent pour cet ensemble de collectes, tel que représenté par la variablePendingScore. Définissez le texte par défaut du bloc de texte sur la couleur blanche.PendingScoreWidget<internal> : text_block = text_block{}Un
bloc de textenomméPickupLevelWidgetavec le spécificateurinternal, pour stocker le widget de texte et afficher le niveau de collecte actuel, tel que représenté par la variablePickupLevel. Définissez le texte par défaut du bloc de texte sur la couleur blanche.PickupLevelWidget<internal> : text_block = text_block{}Une fonction renvoyant un
messagenomméeTotalGameScoreTextqui crée un texte localisable à afficher dans l'interface utilisateur pour indiquer tous les points que le joueur a marqués dans le jeu en général.TotalGameScoreText<localizes>(CurrentTotalGameScore : int) : message = "Total Points: {CurrentTotalGameScore}"Une fonction renvoyant un
messagenomméePendingScoreTextqui crée un texte localisable à afficher dans l'interface utilisateur pour indiquer les points que le joueur a accumulés jusqu'à présent pour cet ensemble de collectes.PendingScoreText<localizes>(CurrentPendingScore : int) : message = "Pending Points: {CurrentPendingScore}"Une fonction renvoyant un
messagenomméePickupLevelTextqui crée un texte localisable à afficher dans l'interface utilisateur pour indiquer le niveau de collecte actuel.PickupLevelText<localizes>(CurrentPickupLevel : int) : message = "Pickup Level: {CurrentPickupLevel}"Ajoutez une expression
blockqui crée le widget de zone de dessin et positionne le texte empilé verticalement sur la gauche de l'écran.<# Étant donné que la zone de dessin ne sera pas créée pendant la durée de vie du gestionnaire de score, créez-la une fois chaque fois qu'un objet de ce type est créé. #> block: set Canvas = canvas: Slots := array: canvas_slot: Anchors := anchors{Minimum := vector2{X := 0.0, Y := 0.25}, Maximum := vector2{X := 0.0, Y := 0.25} } Offsets := margin{Top := 0.0, Left := 25.0, Right := 0.0, Bottom := 0.0} Alignment := vector2{X := 0.0, Y := 0.0} SizeToContent := true Widget := stack_box: Orientation := orientation.Vertical Slots := array: stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := TotalGameScoreWidget stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := PendingScoreWidget stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := PickupLevelWidget
Le code de votre gestionnaire de score
score_managerdoit maintenant être similaire à celui-ci :using { /UnrealEngine.com/Temporary/UI } using { /Fortnite.com/UI } using { /Verse.org/Colors } score_manager := class: var Canvas<internal> : canvas = canvas{} TotalGameScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White} PendingScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White} PickupLevelWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White} MaybePlayer<internal> : ?agent = false MaybePlayerUI<internal> : ?player_ui = false ScoreManagerDevice<internal> : score_manager_device = score_manager_device{} PickupLevelText<private><localizes>(InLevel : int) : message = "Pickup Level: {InLevel}" PendingScoreText<private><localizes>(InPoints : int) : message = "Pending Points: {InPoints}" TotalGameScoreText<private><localizes>(InPoints : int) : message = "Total Points: {InPoints}" var TotalGameScore<private> : int = 0 var PendingScore<private> : int = 0 var PickupLevel<private> : int = 0 <# Étant donné que la zone de dessin ne sera pas créée pendant la durée de vie du gestionnaire de score, créez-la une fois chaque fois qu'un objet de ce type est créé. #> block: set Canvas = canvas: Slots := array: canvas_slot: Anchors := anchors{Minimum := vector2{X := 0.0, Y := 0.25}, Maximum := vector2{X := 0.0, Y := 0.25} } Offsets := margin{Top := 0.0, Left := 25.0, Right := 0.0, Bottom := 0.0} Alignment := vector2{X := 0.0, Y := 0.0} SizeToContent := true Widget := stack_box: Orientation := orientation.Vertical Slots := array: stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := TotalGameScoreWidget stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := PendingScoreWidget stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := PickupLevelWidgetCréez une fonction nommée
UpdateUI()avec le spécificateurprivate, qui met à jour le texte dans l'interface utilisateur avec les dernières valeurs de score et le niveau de collecte actuel.UpdateUI<private>() : void = if (PlayerUI := MaybePlayerUI?): PickupLevelWidget.SetText(PickupLevelText(PickupLevel)) PendingScoreWidget.SetText(PendingScoreText(PendingScore)) PendingScoreWidget.SetText(TotalGameScoreText(TotalGameScore))Créez une fonction nommée
AddScoreManagerToUI()qui met à jour l'interface utilisateur du joueur avec l'interface utilisateur du gestionnaire de score personnalisé.AddScoreManagerToUI<public>() : void = if (PlayerUI := MaybePlayerUI?): PlayerUI.AddWidget(Canvas) UpdateUI()Créez une fonction pour chaque valeur qui s'affiche dans l'interface utilisateur afin que la boucle de jeu puisse mettre à jour les valeurs :
Une fonction nommée
AddPendingScoreToTotalScore()avec le spécificateurpublic. Cette fonction doit ajouter le score en attente au score total du jeu et remettre la valeur du score en attente à0. Vous pouvezreporterla remise à zéro du scorePendingScoreet la mise à jour de l'interface utilisateur après la mise à jour du scoreTotalGameScore. Cela évite d'utiliser une variable temporaire pour contenir la valeur dePendingScoreavant sa remise à zéro.Verse<# Adds PendingScore to TotalGameScore and resets PendingScore to 0.#> AddPendingScoreToTotalScore<public>() : void = defer: set PendingScore = 0 UpdateUI() set TotalGameScore += PendingScoreUne fonction nommée
UpdatePendingScore()avec le spécificateurpublicet un paramètre entier nomméPointsque la fonction ajoutera au score en attente actuel.Verse<# Adds the given amount of points to the pending points. #> UpdatePendingScore<public>(Points : int) : void = set PendingScore += Points UpdateUI()Une fonction nommée
UpdatePickupLevelavec le spécificateurpublicet un paramètre entier nomméLevel, qui est la nouvelle valeur du niveau de collecte actuel.VerseUpdatePickupLevel<public>(Level : int) : void = set PickupLevel = Level UpdateUI()Créez une fonction nommée
AwardScore()avec le spécificateurpublic. Cette fonction attribue le score au joueur en utilisant l'appareil Gestionnaire de score et l'active.Verse<# Awards the score to the player with the Score Manager device, by activating it. #> AwardScore<public>() : void = ScoreManagerDevice.SetScoreAward(TotalGameScore) if (AwardedPlayer := MaybePlayer?): ScoreManagerDevice.Activate(AwardedPlayer)
Votre classe
score_managerdoit maintenant être similaire à ce qui suit :Versescore_manager := class: <# Since we won't recreate the canvas during the score manager lifetime, do it once anytime an object of this type is created.> block: set Canvas = canvas: Slots := array: canvas_slot: Anchors := anchors{Minimum := vector2{X := 0.0, Y := 0.25}, Maximum := vector2{X := 0.0, Y := 0.25} } Offsets := margin{Top := 0.0, Left := 25.0, Right := 0.0, Bottom := 0.0} Alignment := vector2{X := 0.0, Y := 0.0} SizeToContent := trueMaintenant que vous avez créé votre classe
score_manager, créez un constructeur pour que la classe puisse initialiser les variables du joueur depuis le jeu. Notez que vous devez convertir la référence de joueur d'agentàplayerafin d'obtenir une référence à l'IU du joueur.VerseMakeScoreManager<constructor><public>(InPlayer : agent, InScoreManagerDevice : score_manager_device) := score_manager: MaybePlayer := option{InPlayer} MaybePlayerUI := option{GetPlayerUI[player[InPlayer]]}Votre fichier score_manager.verse doit maintenant être similaire à ce qui suit :
Verseusing { /UnrealEngine.com/Temporary/SpatialMath} using { /UnrealEngine.com/Temporary/UI } using { /Fortnite.com/Devices } using { /Fortnite.com/UI } using { /Verse.org/Colors } using { /Verse.org/Simulation } MakeScoreManager<constructor><public>(InPlayer : agent, InScoreManagerDevice : score_manager_device) := score_manager: MaybePlayer := option{InPlayer} MaybePlayerUI := option{GetPlayerUI[player[InPlayer]]}
Mettre à jour le score et l'interface utilisateur dans la boucle de jeu
Procédez comme suit pour créer et mettre à jour votre interface utilisateur pendant le jeu dans le fichier game_coordinator_device.verse :
Ajoutez les propriétés suivantes à la classe
game_coordinator_device:Une variable
score_managernomméeScoreManageravec le spécificateurprivate. Cette instance gère le score et l'interface utilisateur du joueur.var ScoreManager<private> : score_manager = score_manager{}Un appareil
score_manager_devicemodifiable que vous pouvez définir comme le gestionnaire de score dans le niveau. Il s'agit de l'appareil que la classescore_managerva utiliser.@editable ScoreManagerDevice<public> : score_manager_device = score_manager_device{}Une matrice d'entiers modifiable nommée
PointsForPickupLevelavec le spécificateurpublic, pour définir les points que le joueur peut marquer pour chaque niveau de collecte.@editable # Indique le nombre de points que vaut une collecte en fonction de son niveau. PointsForPickupLevel<public> : []int = array{1, 2, 3}
Dans la fonction
StartGame, initialisez la variable du gestionnaire de score en appelant le constructeurMakeScoreManager()avec une référence au joueur et à l'appareil Gestionnaire de score, puis générez l'interface utilisateur afin que le joueur puisse y accéder.VerseStartGame<private>()<suspends> : void = Logger.Print("Trying to start the game...") # We construct a new countdown_timer that'll countdown from InitialCountdownTime once started. # Also construct a new score_manager that'll keep track of the player's score and pickup level. # The countdown_timer and score_manager require a player to show their UI to. # We should have a valid player by now: the one that entered the vehicle, triggering the game start. if (ValidPlayer := MaybePlayer?): Logger.Print("Valid player, starting game...")Dans la fonction
PickupDeliveryLoop()de la boucle de jeu, mettez à jour l'interface utilisateur chaque fois que le niveau de collecte change et que le joueur termine une collecte ou une livraison :VersePickupDeliveryLoop<private>()<suspends> : void = PickupZonesTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} MaxPickupLevel := PickupZonesTags.Length - 1 FirstPickupZoneCompletedEvent := event(){} loop: var PickupLevel : int = 0 var IsFirstPickup : logic = true # Every time the loop restarts, we should reset the pickup level UI through the ScoreManager.Maintenant, à la fin du compte à rebours, attribuez au joueur son score. Dans
HandleCountdownEnd(), appelezScoreManager.AwardScore().HandleCountdownEnd<private>(InPlayer : player)<suspends>:void= TotalTime := CountdownTimer.CountdownEndedEvent.Await() ScoreManager.AwardScore() EndGame.Activate(InPlayer)Votre fichier game_coordinator_device.verse doit maintenant être similaire à ce qui suit :
Verseusing { /Verse.org/Simulation } using { /Fortnite.com/Devices } using { /Fortnite.com/Vehicles } using { /Fortnite.com/Characters } using { /Fortnite.com/Playspaces } using { /Verse.org/Random } using { /UnrealEngine.com/Temporary/Diagnostics } using { /UnrealEngine.com/Temporary/SpatialMath } using { /EpicGames.com/Temporary/Curves } using { /Verse.org/Simulation/Tags }