Nettoyage et réinitialisation

*Ce contenu est traduit en utilisant l'IA (Beta) et peut contenir des erreurs. Pour consulter cette page en anglais, clique ici.

Il est temps de codifier la dernière phase du jeu : le nettoyage et le réinitialiser. Le code dans cette phase garantit que les boucles de jeu s'arrêtent à l'intermission et que les matchs futurs commencent pour chaque joueur.

Mise à jour de linterface utilisateur graphique

Avant de nettoyer et de réinitialiser, informez les joueurs comment le jeu s'est terminé en utilisant le Gestionnaire d'affichage pour montrer le statut approprié.

Obtenir le nom du gagnant

Commencez par obtenir le nom du joueur gagnant s'il y en avait un. Auparavant, le code vérifiait si la taille de la table des joueurs actifs était réduite de 1. Pour obtenir le nom du joueur restant, retournez le nom au premier index de cette table.

  1. Dans PlayerManager, commencez une nouvelle fonction de module nommée getWinnerName() .


    function PlayerManager.getWinnerName()
    end
    -- Événements
    Players.PlayerAdded:Connect(onPlayerJoin)
  2. Ajoutez une if statement qui s'exécute si quelque chose existe dans activePlayers[1]. Bien que le nombre de tables ait été vérifié auparavant, le joueur pourrait avoir quitté ou quitté le jeu.


    function PlayerManager.getWinnerName()
    local winningPlayer = activePlayers[1]
    if winningPlayer then
    end
    end
  3. Dans la déclaration if :

    • Renvoie le nom du joueur.
    • Pour l'autre, renvoyez une chaîne d'erreur.

    function PlayerManager.getWinnerName()
    local winningPlayer = activePlayers[1]
    if winningPlayer then
    return winningPlayer.Name
    else
    return "Error: No winning player found"
    end
    end

Obtenir le statut de fin

Utilisez une fonction de module pour prendre les informations de l'état correct, soit que le minuteur se termine, soit qu'un joueur quitte. Ensuite, envoyez cette variable d'état à DisplayManager pour mettre à jour le GUI de statut avec le message approprié.

  1. Dans MatchManager , codez une nouvelle fonction de module nommée getEndStatus() avec un paramètre nommé endState . Pour stocker le message qui sera envoyé, ajoutez une variable vide nommée 1> statusToReturn1> .


    function MatchManager.prepareGame()
    playerManager.sendPlayersToMatch()
    matchStart:Fire()
    end
    function MatchManager.getEndStatus(endState)
    local statusToReturn
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  2. Définissez la valeur de statusToReturn en utilisant les déclarations if et elif. Vérifiez les variables d'état final : FoundWinner et TimerUp. Pour le débogage, incluez un else à la terminer.


    function MatchManager.getEndStatus(endState)
    local statusToReturn
    if endState == gameSettings.endStates.FoundWinner then
    elseif endState == gameSettings.endStates.TimerUp then
    else
    end
    end
  3. Ajoutez les éléments suivants pour chaque condition :

    FoundWinner

    • Un variable pour le gagnant en utilisant playerManager.getWinnerName() .
    • Mise à jour statusToReturn avec une chaîne annonçant le gagnant.

    TimerUp

    • Mise à jour statusToReturn avec une chaîne annonçant le temps écoulé.

    Else

    • Mise à jour statusToReturn avec un message d'erreur dans le cas où il y a des problèmes pour obtenir le message de fin de partie.

    function MatchManager.getEndStatus(endState)
    local statusToReturn
    if endState == gameSettings.endStates.FoundWinner then
    local winnerName = playerManager.getWinnerName()
    statusToReturn = "Winner is : " .. winnerName
    elseif endState == gameSettings.endStates.TimerUp then
    statusToReturn = "Time ran out!"
    else
    statusToReturn = "Error found"
    end
    end
  4. Envoyez le message en entrant return statusToReturn .


    function MatchManager.getEndStatus(endState)
    local statusToReturn
    if endState == gameSettings.endStates.FoundWinner then
    local winnerName = playerManager.getWinnerName()
    statusToReturn = "Winner is : " .. winnerName
    elseif endState == gameSettings.endStates.TimerUp then
    statusToReturn = "Time ran out!"
    else
    statusToReturn = "Error found"
    end
    return statusToReturn
    end

Affichage et test

Obtenez l'annonce mise à jour dans GameManager et affichez-la aux joueurs en utilisant le Gestionnaire d'affichage.

  1. Ouvrez GameManager . In while true do loop, delete the last print statement. Then, create a variable named endStatus. Set it equal to calling matchManager.getEndStatus(endState) .


    while true do
    displayManager.updateStatus("Waiting for Players")
    repeat
    task.wait(gameSettings.intermissionDuration)
    until #Players:GetPlayers() >= gameSettings.minimumPlayers
    displayManager.updateStatus("Get ready!")
    task.wait(gameSettings.transitionTime)
    matchManager.prepareGame()
    local endState = matchEnd.Event:Wait()
    local endStatus = matchManager.getEndStatus(endState)
    end
  2. Pour afficher le message renvoyé dans l'étiquette GUI, appelez displayManager.updateStatus() et passez en endStatus .


    local endStatus = matchManager.getEndStatus(endState)
    displayManager.updateStatus(endStatus)
  3. Le jeu s'arrête pour permettre aux joueurs de voir le message, ajoutez un temps d'attente en utilisant transitionTime.


    local endStatus = matchManager.getEndStatus(endState)
    displayManager.updateStatus(endStatus)
    task.wait(gameSettings.transitionTime)
  4. Démarrez un testeur de serveur et vérifiez que les joueurs voient les messages suivants pour le temps écoulé et les conditions de gagnant.

    condition de fin du temps
    Condition du joueur gagnant

Conseils de débogage

À ce stade, vous n'êtes pas en mesure de voir les messages, essayez l'un des éléments suivants.

  • Si votre message de statut final est « Erreur trouvée », aucune des conditions n'a été réussie. Vérifiez le code dans MatchManager.getEndStatus() contre les exemples de code.
  • Si l'état de fin ne s'affiche pas, vérifiez que task.wait(gameSettings.transitionTime) est après l'envoi du message à displayManager.

Démarrer de nouvelles matchs

Avant de commencer une nouvelle correspondre, il y aura une transition rapide. Cela donne aux joueurs le temps de voir le statut de fin et rend le fait d'être téléporté dans le lobby moins soudain.

À la fin de la transition, les joueurs restants seront retirés de l'arène, et tout le code sera réinitialiser. Cela garantit que les joueurs commencent la prochaine partie avec une version propre du jeu.

Gestion des transition

Lorsque les joueurs se transforment en état de transition, enlève leurs armes.

  1. Dans PlayerManager, trouvez les fonctions locales. Copiez et collez le code en surbrillance pour removePlayerWeapon() ci-dessous. Le code supprime l'arme d'un joueur individuel s'il est activement équipé ou dans le sac à dos du joueur.


    local function removePlayerWeapon(whichPlayer)
    -- Vérifiez si un joueur existe au cas où il se serait déconnecté ou quitté.
    if whichPlayer then
    local character = whichPlayer.Character
    -- Si le joueur l'a actuellement sur son personnage
    local weapon = character:FindFirstChild("Weapon")
    if weapon then
    weapon:Destroy()
    end
    -- Si le joueur a l'arme dans son sac à dos
    local backpackWeapon = whichPlayer.Backpack:FindFirstChild("Weapon")
    if backpackWeapon then
    backpackWeapon:Destroy()
    end
    else
    print("No player to remove weapon")
    end
    end
  2. Démarrez une nouvelle fonction de module nommée removeAllWeapons() .


    function PlayerManager.removeAllWeapons()
    end
    -- Événements
    Players.PlayerAdded:Connect(onPlayerJoin)
    return PlayerManager
  3. Dans cette fonction, utilisez un for loop pour aller à travers la table des joueurs actifs. Dans le loop, appelez removePlayerWeapon() et passez dans le joueur trouvé.


    function PlayerManager.removeAllWeapons()
    for playerKey, whichPlayer in activePlayers do
    removePlayerWeapon(whichPlayer)
    end
    end

Nettoyage entre les matchs

Le nettoyage sera sa propre fonction dans MatchManager. Pour l'instant, le nettoyage utilisera simplement cette fonction créée précédemment pour supprimer les armes des joueurs. Au fur et à mesure que vous élargissez le jeu, plus peut être ajouté, comme des fonctions pour réinitialiser une carte qui a changé pendant un correspondre.

  1. Ouvrez MatchManager. Ajoutez une nouvelle fonction de module nommée cleanupMatch() . Dans cette fonction, appelez playerManager.removeAllWeapons() .


    function MatchManager.cleanupMatch()
    playerManager.removeAllWeapons()
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  2. Ensuite, appelez la fonction de nettoyage. Ouvrez GameManager et trouvez le while true do loop. Ainsi, les joueurs ont des armes supprimées pendant l'intermission de fin, appelez matchManager.cleanupMatch() avant le dernier task.wait() .


    while true do
    displayManager.updateStatus("Waiting for Players")
    repeat
    task.wait(gameSettings.intermissionDuration)
    until #Players:GetPlayers() >= gameSettings.minimumPlayers
    displayManager.updateStatus("Get ready!")
    task.wait(gameSettings.transitionTime)
    matchManager.prepareGame()
    local endState = matchEnd.Event:Wait()
    local endStatus = matchManager.getEndStatus(endState)
    displayManager.updateStatus(endStatus)
    matchManager.cleanupMatch()
    task.wait(gameSettings.transitionTime)
    end
  3. Démarrez un serveur de test et exécutez un correspondre. Attendez que le minuteur se termine et confirmez que l'arme du joueur est retirée pendant l'intermission de la fin du jeu.

    Pendant un match
    Après le match

Réinitialisation des matchs

Vous avez peut-être remarqué quelques autres choses dans le jeu, comme les joueurs qui restent dans l'arène après la fin d'un match. Avec le match nettoyé, le jeu réinitialise ensuite. Cela inclut l'envoi de joueurs dans l'arène et le nettoyage de la table des joueurs actifs. Avec un réinitialisation en emplacement, un boucle de jeu peut s'exécuter infiniment.

Tout d'abord, commencez une fonction pour envoyer les joueurs dans le lobby.

  1. Dans PlayerManager :

    • Créer une fonction de module nommée resetPlayers() .
    • Ajoutez un for loop pour itérer à travers les joueurs actifs.
    • Dans la boucle, appelez respawnPlayerInLobby() et passez le joueur en tant que paramètre.

    function PlayerManager.resetPlayers()
    for playerKey, whichPlayer in activePlayers do
    respawnPlayerInLobby(whichPlayer)
    end
    end
    -- Événements
    Players.PlayerAdded:Connect(onPlayerJoin)
    return PlayerManager
  2. Assurez-vous que la table activePlayers est vide pour le prochain match en laissant-la équivalente à {}, ce qui est un moyen rapide de réinitialiser à une table vide.


    function PlayerManager.resetPlayers()
    for playerKey, whichPlayer in activePlayers do
    respawnPlayerInLobby(whichPlayer)
    end
    activePlayers = {}
    end
  3. Ouvrez MatchManager. Codez une nouvelle fonction de module nommée resetMatch() et appelez playerManager.resetPlayers().


    function MatchManager.resetMatch()
    playerManager.resetPlayers()
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  4. Retournez à GameManager . Au bout du compte-à-rebours, appelez matchManager.resetMatch() .


    while true do
    displayManager.updateStatus("Waiting for Players")
    repeat
    task.wait(gameSettings.intermissionDuration)
    until #Players:GetPlayers() >= gameSettings.minimumPlayers
    displayManager.updateStatus("Get ready!")
    task.wait(gameSettings.transitionTime)
    matchManager.prepareGame()
    local endState = matchEnd.Event:Wait()
    local endStatus = matchManager.getEndStatus(endState)
    displayManager.updateStatus(endStatus)
    matchManager.cleanupMatch()
    task.wait(gameSettings.transitionTime)
    matchManager.resetMatch()
    end
  5. Démarrez un serveur de test et exécutez un correspondre. Confirmez que vous pouvez au moins passer à travers deux boucles de jeu sans aucune erreur.

Scripts terminés

Ceux-ci sont des scripts terminés pour vérifier vos travaux.

Script de GameManager


-- Services
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
-- Scripts de module
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))
-- Événements
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
while true do
displayManager.updateStatus("Waiting for Players")
repeat
task.wait(gameSettings.intermissionDuration)
until #Players:GetPlayers() >= gameSettings.minimumPlayers
displayManager.updateStatus("Get ready!")
task.wait(gameSettings.transitionTime)
matchManager.prepareGame()
local endState = matchEnd.Event:Wait()
local endStatus = matchManager.getEndStatus(endState)
displayManager.updateStatus(endStatus)
matchManager.cleanupMatch()
task.wait(gameSettings.transitionTime)
matchManager.resetMatch()
end

Script de MatchManager


local MatchManager = {}
-- Services
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Scripts de module
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local playerManager = require(moduleScripts:WaitForChild("PlayerManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))
local timer = require(moduleScripts:WaitForChild("Timer"))
-- Événements
local events = ServerStorage:WaitForChild("Events")
local matchStart = events:WaitForChild("MatchStart")
local matchEnd = events:WaitForChild("MatchEnd")
-- Valeurs
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local timeLeft = displayValues:WaitForChild("TimeLeft")
-- Crée un nouvel objet de minuterie à utiliser pour suivre le temps du match.
local myTimer = timer.new()
-- Fonctions locales
local function stopTimer()
myTimer:stop()
end
local function timeUp()
matchEnd:Fire(gameSettings.endStates.TimerUp)
end
local function startTimer()
myTimer:start(gameSettings.matchDuration)
myTimer.finished:Connect(timeUp)
while myTimer:isRunning() do
-- Ajouter +1 fait en sorte que l'afficheur de temps s'affiche à 1 au lieu de 0.
timeLeft.Value = (math.floor(myTimer:getTimeLeft() + 1))
-- En ne définissant pas le temps d'attente, il offre un meilleur suivi
task.wait()
end
end
-- Fonctions de module
function MatchManager.prepareGame()
playerManager.sendPlayersToMatch()
matchStart:Fire()
end
function MatchManager.getEndStatus(endState)
local messageToReturn
if endState == gameSettings.endStates.FoundWinner then
local winnerName = playerManager.getWinnerName()
messageToReturn = "Winner is : " .. winnerName
elseif endState == gameSettings.endStates.TimerUp then
messageToReturn = "Time ran out!"
else
messageToReturn = "Error found"
end
return messageToReturn
end
function MatchManager.cleanupMatch()
playerManager.removeAllWeapons()
end
function MatchManager.resetMatch()
playerManager.resetPlayers()
end
matchStart.Event:Connect(startTimer)
matchEnd.Event:Connect(stopTimer)
return MatchManager

Script PlayerManager


local PlayerManager = {}
-- Services
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Modules
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- Événements
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
-- Variables de carte
local lobbySpawn = workspace.Lobby.StartSpawn
local arenaMap = workspace.Arena
local spawnLocations = arenaMap.SpawnLocations
-- Valeurs
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local playersLeft = displayValues:WaitForChild("PlayersLeft")
-- Variables du joueur
local activePlayers = {}
local playerWeapon = ServerStorage.Weapon
local function checkPlayerCount()
if #activePlayers == 1 then
matchEnd:Fire(gameSettings.endStates.FoundWinner)
print("Found winner")
end
end
local function removeActivePlayer(player)
print("removing player")
for playerKey, whichPlayer in activePlayers do
if whichPlayer == player then
table.remove(activePlayers, playerKey)
playersLeft.Value = #activePlayers
checkPlayerCount()
end
end
end
local function respawnPlayerInLobby(player)
player.RespawnLocation = lobbySpawn
player:LoadCharacter()
end
local function preparePlayer(player, whichSpawn)
player.RespawnLocation = whichSpawn
player:LoadCharacter()
local character = player.Character or player.CharacterAdded:Wait()
-- Donnez un outil au joueur
local sword = playerWeapon:Clone()
sword.Parent = character
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
respawnPlayerInLobby(player)
removeActivePlayer(player)
end)
end
local function onPlayerJoin(player)
player.RespawnLocation = lobbySpawn
end
local function removePlayerWeapon(whichPlayer)
-- Vérifiez si un joueur existe au cas où il se serait déconnecté ou quitté.
if whichPlayer then
local character = whichPlayer.Character
-- Si le joueur l'a actuellement sur son personnage
local weapon = character:FindFirstChild("Weapon")
if weapon then
weapon:Destroy()
end
-- Si le joueur a l'arme dans son sac à dos
local backpackWeapon = whichPlayer.Backpack:FindFirstChild("Weapon")
if backpackWeapon then
backpackWeapon:Destroy()
end
else
print("No player to remove weapon")
end
end
function PlayerManager.sendPlayersToMatch()
local availableSpawnPoints = spawnLocations:GetChildren()
for playerKey, whichPlayer in Players:GetPlayers() do
table.insert(activePlayers,whichPlayer)
-- Obtient un lieu d'apparition et le supprime de la table pour que le prochain joueur obtienne le prochain lieu d'apparition
local spawnLocation = table.remove(availableSpawnPoints, 1)
preparePlayer(whichPlayer, spawnLocation)
end
playersLeft.Value = #activePlayers
end
function PlayerManager.getWinnerName()
local winningPlayer = activePlayers[1]
if winningPlayer then
return winningPlayer.Name
else
return "Error: No player found"
end
end
function PlayerManager.removeAllWeapons()
for playerKey, whichPlayer in activePlayers do
removePlayerWeapon(whichPlayer)
end
end
function PlayerManager.resetPlayers()
for playerKey, whichPlayer in activePlayers do
respawnPlayerInLobby(whichPlayer)
end
activePlayers = {}
end
-- Événements
Players.PlayerAdded:Connect(onPlayerJoin)
return PlayerManager