Il est temps de coder la dernière phase du jeu : nettoyer et réinitialiser.Le code dans cette phase garantit que les boucles de jeu passent à l'intermission et que les matchs futurs commencent de la même façon pour chaque joueur.
Mise à jour de l'interface utilisateur
Avant de faire le nettoyage et la réinitialisation, informez les joueurs comment le jeu s'est terminé en utilisant le gestionnaire d'affichage pour afficher le statut approprié.
Obtenez 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 à 1.Pour obtenir le nom du joueur restant, retournez le nom au premier index de cette table.
Dans PlayerManager, lancez une nouvelle fonction de module nommée getWinnerName().
function PlayerManager.getWinnerName()end-- ÉvénementsPlayers.PlayerAdded:Connect(onPlayerJoin)Ajoutez une déclaration if qui s'exécute si quelque chose existe dans activePlayers[1] .Bien que le nombre de tables ait été vérifié avant, le joueur pourrait avoir été déconnecté ou quitté le jeu.
function PlayerManager.getWinnerName()local winningPlayer = activePlayers[1]if winningPlayer thenendendDans la déclaration if :
- Renvoie le nom du joueur.
- Pour le reste, renvoiez une chaîne d'erreur.
function PlayerManager.getWinnerName()local winningPlayer = activePlayers[1]if winningPlayer thenreturn winningPlayer.Nameelsereturn "Error: No winning player found"endend
Obtenir le statut final
Utilisez une fonction de module pour prendre des informations de l'état final correct, que la minuterie se termine ou qu'un joueur soit laissé.Ensuite, envoyez cette variable d'état au gestionnaire d'affichage pour mettre à jour le statut GUI avec le message approprié.
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 statusToReturn .
function MatchManager.prepareGame()playerManager.sendPlayersToMatch()matchStart:Fire()endfunction MatchManager.getEndStatus(endState)local statusToReturnendmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerDéfinissez la valeur de statusToReturn en utilisant les déclarations if et elseif.Vérifiez les variables d'état final : FoundWinner et TimerUp .Pour vérifier les erreurs, incluez un autre à la fin.
function MatchManager.getEndStatus(endState)local statusToReturnif endState == gameSettings.endStates.FoundWinner thenelseif endState == gameSettings.endStates.TimerUp thenelseendendAjoutez ce qui suit pour chaque condition :
FoundWinner
- Une 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 que le temps est écoulé.
Else
- Mise à jour statusToReturn avec un message d'erreur en cas de problèmes pour obtenir le message de fin de jeu.
function MatchManager.getEndStatus(endState)local statusToReturnif endState == gameSettings.endStates.FoundWinner thenlocal winnerName = playerManager.getWinnerName()statusToReturn = "Winner is : " .. winnerNameelseif endState == gameSettings.endStates.TimerUp thenstatusToReturn = "Time ran out!"elsestatusToReturn = "Error found"endendRenvoyez le message en tapant return statusToReturn.
function MatchManager.getEndStatus(endState)local statusToReturnif endState == gameSettings.endStates.FoundWinner thenlocal winnerName = playerManager.getWinnerName()statusToReturn = "Winner is : " .. winnerNameelseif endState == gameSettings.endStates.TimerUp thenstatusToReturn = "Time ran out!"elsestatusToReturn = "Error found"endreturn statusToReturnend
Affichage et test
Obtenez l'annonce mise à jour dans GameManager et affichez-la aux joueurs en utilisant le DisplayManager.
Ouvrez GameManager .Dans la boucle while vraie, supprimez la dernière déclaration d'impression.Ensuite, créez une variable nommée endStatus.Définissez-le comme l'appel de matchManager.getEndStatus(endState).
while true dodisplayManager.updateStatus("Waiting for Players")repeattask.wait(gameSettings.intermissionDuration)until #Players:GetPlayers() >= gameSettings.minimumPlayersdisplayManager.updateStatus("Get ready!")task.wait(gameSettings.transitionTime)matchManager.prepareGame()local endState = matchEnd.Event:Wait()local endStatus = matchManager.getEndStatus(endState)endPour afficher le message retourné dans l'étiquette GUI, appelez displayManager.updateStatus() et passez en endStatus.
local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)Donc, le jeu s'arrête pour laisser les joueurs voir le message, ajoutez une attente en utilisant transitionTime.
local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)task.wait(gameSettings.transitionTime)Démarrez un serveur de test et vérifiez que les joueurs voient les messages suivants pour le temps écoulé et les conditions du joueur gagnant.
La condition temps écoulé est activée Conditions du joueur gagnant
Conseils de dépannage
À ce stade, vous ne pouvez pas voir les messages, essayez l'une des options suivantes.
- Si votre message de statut final est « Erreur trouvée », aucune des conditions n'a réussi. Vérifiez le code dans MatchManager.getEndStatus() contre les échantillons de code.
- Si l'état final n'est pas affiché, vérifiez que task.wait(gameSettings.transitionTime) est après l'envoi du message à displayManager.
Débuter de nouveaux matchs
Avant le début d'un nouveau match, il y aura une brève transition.Cela donne aux joueurs le temps de voir l'état final et de rendre le téléportation dans le lobby moins soudaine.
À la fin de la transition, les joueurs restants seront retirés de l'arène, et tout le code sera réinitialisé.Cela garantit que les joueurs commenceront le prochain match avec une version propre du jeu.
Gérer les transitions
Lorsque les joueurs se déplacent dans l'état de transition, retirez leurs armes.
Dans PlayerManager, trouvez les fonctions locales.Copiez et collez le code mis en évidence 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 déconnecterait ou partirait.if whichPlayer thenlocal character = whichPlayer.Character-- Si le joueur l'a actuellement sur son personnagelocal weapon = character:FindFirstChild("Weapon")if weapon thenweapon:Destroy()end-- Si le joueur a l'arme dans son sac à doslocal backpackWeapon = whichPlayer.Backpack:FindFirstChild("Weapon")if backpackWeapon thenbackpackWeapon:Destroy()endelseprint("No player to remove weapon")endendDémarrez une nouvelle fonction de module nommée removeAllWeapons().
function PlayerManager.removeAllWeapons()end-- ÉvénementsPlayers.PlayerAdded:Connect(onPlayerJoin)return PlayerManagerDans cette fonction, utilisez une boucle for pour parcourir la table des joueurs actifs. Dans la boucle, appelez removePlayerWeapon() et passez le joueur trouvé.
function PlayerManager.removeAllWeapons()for playerKey, whichPlayer in activePlayers doremovePlayerWeapon(whichPlayer)endend
Nettoyer 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 match.
Ouvrir le gestionnaire de match. Ajoutez une nouvelle fonction de module nommée cleanupMatch(). Dans cette fonction, appelez playerManager.removeAllWeapons().
function MatchManager.cleanupMatch()playerManager.removeAllWeapons()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerEnsuite, appelez la fonction de nettoyage.Ouvrez GameManager et trouvez la boucle while vraie.Donc, les joueurs ont des armes supprimées pendant l'intermission de fin, appelez matchManager.cleanupMatch() avant le dernier task.wait().
while true dodisplayManager.updateStatus("Waiting for Players")repeattask.wait(gameSettings.intermissionDuration)until #Players:GetPlayers() >= gameSettings.minimumPlayersdisplayManager.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)endDémarrez un serveur de test et exécutez un match. Attendez que le minuteur expire et confirmez que l'arme du joueur est supprimée pendant l'intermission de la fin du jeu.
Pendant un match Après le match
Réinitialiser les correspondances
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é, réinitialisez ensuite le jeu.Cela inclut l'envoi de joueurs dans l'arène de retour dans le lobby et le nettoyage de la table des joueurs actifs.Avec une réinitialisation en place, une boucle de jeu peut s'exécuter indéfiniment.
Tout d'abord, lancez une fonction pour renvoyer les joueurs dans le lobby.
Dans PlayerManager :
- Créez une fonction de module nommée resetPlayers().
- Ajoutez une boucle for pour itérer sur 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 dorespawnPlayerInLobby(whichPlayer)endend-- ÉvénementsPlayers.PlayerAdded:Connect(onPlayerJoin)return PlayerManagerAssurez-vous que la table activePlayers est vide pour le prochain match en la configurant à l'égal de {}, ce qui est un moyen rapide de revenir à une table vide.
function PlayerManager.resetPlayers()for playerKey, whichPlayer in activePlayers dorespawnPlayerInLobby(whichPlayer)endactivePlayers = {}endOuvrez MatchManager. Codez une nouvelle fonction de module nommée resetMatch() et appelez playerManager.resetPlayers() .
function MatchManager.resetMatch()playerManager.resetPlayers()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerRetournez à GameManager . À la fin du cycle while true, appelez matchManager.resetMatch().
while true dodisplayManager.updateStatus("Waiting for Players")repeattask.wait(gameSettings.intermissionDuration)until #Players:GetPlayers() >= gameSettings.minimumPlayersdisplayManager.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()endDémarrez un serveur de test et exécutez un match. Confirmez que vous pouvez au moins traverser deux boucles de jeu sans erreurs.
Scripts terminés
Ci-dessous, les scripts terminés pour vérifier à nouveau votre travail.
Script du gestionnaire de jeu
-- Serviceslocal ServerStorage = game:GetService("ServerStorage")local Players = game:GetService("Players")-- Scripts de modulelocal moduleScripts = ServerStorage:WaitForChild("ModuleScripts")local matchManager = require(moduleScripts:WaitForChild("MatchManager"))local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))-- Événementslocal events = ServerStorage:WaitForChild("Events")local matchEnd = events:WaitForChild("MatchEnd")while true dodisplayManager.updateStatus("Waiting for Players")repeattask.wait(gameSettings.intermissionDuration)until #Players:GetPlayers() >= gameSettings.minimumPlayersdisplayManager.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 garantit que l'affichage du temps se termine à 1 au lieu de 0.
timeLeft.Value = (myTimer:getTimeLeft() + 1) // 1
-- En ne définissant pas l'heure d'attente, il offre une boucle plus précise
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")
-- Moduleurs
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 au joueur un outil
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 déconnecterait ou partirait.
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 l'enlève ensuite de la table afin 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